diff --git a/API/pom.xml b/API/pom.xml index 92e332d..f36a3f5 100644 --- a/API/pom.xml +++ b/API/pom.xml @@ -5,7 +5,7 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/DistributionMode.java b/API/src/main/java/su/nightexpress/excellentenchants/api/DistributionMode.java new file mode 100644 index 0000000..1ad0f35 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/DistributionMode.java @@ -0,0 +1,7 @@ +package su.nightexpress.excellentenchants.api; + +public enum DistributionMode { + + VANILLA, + CUSTOM +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ObtainType.java b/API/src/main/java/su/nightexpress/excellentenchants/api/DistributionWay.java similarity index 67% rename from API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ObtainType.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/DistributionWay.java index da894e1..534e84b 100644 --- a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ObtainType.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/DistributionWay.java @@ -1,18 +1,18 @@ -package su.nightexpress.excellentenchants.api.enchantment; +package su.nightexpress.excellentenchants.api; import org.jetbrains.annotations.NotNull; -public enum ObtainType { +public enum DistributionWay { ENCHANTING("Enchanting_Table"), VILLAGER("Villagers"), LOOT_GENERATION("Loot_Generation"), FISHING("Fishing"), - MOB_SPAWNING("Mob_Spawning"); + MOB_EQUIPMENT("Mob_Equipment"); private final String pathName; - ObtainType(@NotNull String pathName) { + DistributionWay(@NotNull String pathName) { this.pathName = pathName; } diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/Modifier.java b/API/src/main/java/su/nightexpress/excellentenchants/api/Modifier.java new file mode 100644 index 0000000..d832bc4 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/Modifier.java @@ -0,0 +1,148 @@ +package su.nightexpress.excellentenchants.api; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.StringUtil; + +public class Modifier { + + private double base; + private double perLevel; + private double step; + private double cap; + private ModifierAction action; + + public Modifier(double base, double perLevel, double step, double cap, @NotNull ModifierAction action) { + this.setBase(base); + this.setPerLevel(perLevel); + this.setStep(step); + this.setCap(cap); + this.setAction(action); + } + + @NotNull + public static Modifier add(double base, double perLevel, double step) { + return add(base, perLevel, step, -1); + } + + @NotNull + public static Modifier multiply(double base, double perLevel, double step) { + return multiply(base, perLevel, step, -1); + } + + @NotNull + public static Modifier add(double base, double perLevel, double step, double cap) { + return new Modifier(base, perLevel, step, cap, ModifierAction.ADD); + } + + @NotNull + public static Modifier multiply(double base, double perLevel, double step, double cap) { + return new Modifier(base, perLevel, step, cap, ModifierAction.MULTIPLY); + } + + @NotNull + public static Modifier read(@NotNull FileConfig cfg, @NotNull String path, @NotNull Modifier def, String ... comments) { + return new ConfigValue<>(path, + (cfg2, path2, def2) -> Modifier.read(cfg2, path2), + (cfg2, path2, mod) -> mod.write(cfg2, path2), + def, + comments + ).read(cfg); + } + + @NotNull + public static Modifier read(@NotNull FileConfig cfg, @NotNull String path) { + double base = ConfigValue.create(path + ".Base", 0D, + "Start modifier value." + ).read(cfg); + + double perLevel = ConfigValue.create(path + ".Per_Level", 0D, + "Additional value calculated by enchantment level step (see below). Formula: * " + ).read(cfg); + + double step = ConfigValue.create(path + ".Step" , 1D, + "Defines level step for 'Per_Level' value calculation. Formula: / " + ).read(cfg); + + double cap = ConfigValue.create(path + ".Cap", -1, + "Sets a limit for the final (base & per level calculations) value.", + "Set '-1' for no limit." + ).read(cfg); + + ModifierAction action = ConfigValue.create(path + ".Action", ModifierAction.class, ModifierAction.ADD, + "Sets action performed between 'Base' and final 'Per_Level' values.", + "Available types: " + StringUtil.inlineEnum(ModifierAction.class, ", ") + ).read(cfg); + + return new Modifier(base, perLevel, step, cap, action); + } + + public void write(@NotNull FileConfig cfg, @NotNull String path) { + cfg.set(path + ".Base", this.getBase()); + cfg.set(path + ".Per_Level", this.getPerLevel()); + cfg.set(path + ".Step", this.getStep()); + cfg.set(path + ".Cap", this.getCap()); + cfg.set(path + ".Action", this.getAction().name()); + } + + public double getValue(int level) { + if (/*level == 1 || */this.perLevel == 0D) return this.capValue(this.getBase()); + + //level -= 1; + + double step = this.getStep() == 0D ? 1D : Math.floor((double) level / this.getStep()); + double result = this.action.math(this.getBase(), this.getPerLevel() * step); + + return this.capValue(result); + } + + public double capValue(double result) { + return this.cap > 0 ? Math.min(result, this.cap) : result; + } + + public int getIntValue(int level) { + return (int) this.getValue(level); + } + + public double getBase() { + return this.base; + } + + public void setBase(double base) { + this.base = base; + } + + public double getPerLevel() { + return this.perLevel; + } + + public void setPerLevel(double perLevel) { + this.perLevel = perLevel; + } + + public double getStep() { + return step; + } + + public void setStep(double step) { + this.step = step; + } + + public double getCap() { + return cap; + } + + public void setCap(double cap) { + this.cap = cap; + } + + @NotNull + public ModifierAction getAction() { + return this.action; + } + + public void setAction(@NotNull ModifierAction action) { + this.action = action; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/ModifierAction.java b/API/src/main/java/su/nightexpress/excellentenchants/api/ModifierAction.java similarity index 88% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/ModifierAction.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/ModifierAction.java index 06b719d..b033755 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/ModifierAction.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/ModifierAction.java @@ -1,4 +1,4 @@ -package su.nightexpress.excellentenchants.enchantment.util; +package su.nightexpress.excellentenchants.api; import org.jetbrains.annotations.NotNull; diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/EnchantmentData.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/EnchantmentData.java new file mode 100644 index 0000000..d5c1695 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/EnchantmentData.java @@ -0,0 +1,193 @@ +package su.nightexpress.excellentenchants.api.enchantment; + +import org.bukkit.World; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.distribution.DistributionOptions; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.Lists; +import su.nightexpress.nightcore.util.placeholder.PlaceholderMap; + +import java.util.List; +import java.util.Set; + +public interface EnchantmentData { + + @NotNull PlaceholderMap getPlaceholders(int level); + + @NotNull FileConfig getConfig(); + + boolean load(); + + boolean checkServerRequirements(); + + boolean isAvailableToUse(@NotNull LivingEntity entity); + + boolean isAvailableToUse(@NotNull World world); + + boolean checkEnchantCategory(@NotNull ItemStack item); + + boolean checkItemCategory(@NotNull ItemStack item); + + @NotNull DistributionOptions getDistributionOptions(); + + @NotNull Rarity getRarity(); + + void setRarity(@NotNull Rarity rarity); + + @NotNull String getId(); + + @NotNull String getName(); + + @NotNull + default String getNameFormatted(int level) { + return this.getNameFormatted(level, -1); + } + + @NotNull String getNameFormatted(int level, int charges); + + @NotNull List getDescription(); + + @NotNull List getDescriptionFormatted(); + + @NotNull List getDescriptionReplaced(int level); + + @NotNull EnchantmentTarget getCategory(); + + @NotNull Enchantment getEnchantment(); + + void setEnchantment(@NotNull Enchantment enchantment); + + ItemCategory[] getItemCategories(); + + EquipmentSlot[] getSlots(); + + default boolean hasConflicts() { + return !this.getConflicts().isEmpty(); + } + + @NotNull Set getConflicts(); + + int getMinLevel(); + + int getMaxLevel(); + + //int getMaxMergeLevel(); + + //int getAnvilMergeCost(int level); + + int getMinCost(int level); + + int getMaxCost(int level); + + default boolean isCurse() { + return false; + } + + boolean isTreasure(); + + boolean hasVisualEffects(); + + boolean isChargesEnabled(); + + boolean isChargesCustomFuel(); + + int getChargesMax(int level); + + int getChargesConsumeAmount(int level); + + int getChargesRechargeAmount(int level); + + @NotNull ItemStack getChargesFuel(); + + boolean isChargesFuel(@NotNull ItemStack item); + + default int getCharges(@NotNull ItemStack item) { + ItemMeta meta = item.getItemMeta(); + return meta == null ? 0 : this.getCharges(meta); + } + + int getCharges(@NotNull ItemMeta meta); + + void setCharges(@NotNull ItemStack item, int level, int amount); + + boolean isFullOfCharges(@NotNull ItemStack item); + + boolean isOutOfCharges(@NotNull ItemStack item); + + void restoreCharges(@NotNull ItemStack item, int level); + + void fuelCharges(@NotNull ItemStack item, int level); + + void consumeCharges(@NotNull ItemStack item, int level); + + void consumeChargesNoUpdate(@NotNull ItemStack item, int level); + + + + + void setDisplayName(@NotNull String displayName); + + default void setDescription(@NotNull String... description) { + this.setDescription(Lists.newList(description)); + } + + void setDescription(@NotNull List description); + + boolean isHiddenFromList(); + + void setHiddenFromList(boolean hiddenFromList); + + void setTreasure(boolean treasure); + + void setStartLevel(int levelMin); + + void setMaxLevel(int levelMax); + + //void setMaxMergeLevel(int maxMergeLevel); + + @NotNull Modifier getMinCost(); + + void setMinCost(@NotNull Modifier minCost); + + @NotNull Modifier getMaxCost(); + + void setMaxCost(@NotNull Modifier maxCost); + + //@NotNull Modifier getAnvilMergeCost(); + + //void setAnvilMergeCost(@NotNull Modifier anvilMergeCost); + + default void setConflicts(@NotNull String... conflicts) { + this.setConflicts(Lists.newSet(conflicts)); + } + + void setConflicts(@NotNull Set conflicts); + + void setVisualEffects(boolean visualEffects); + + void setChargesEnabled(boolean chargesEnabled); + + void setChargesCustomFuel(boolean chargesCustomFuel); + + @NotNull Modifier getChargesMax(); + + void setChargesMax(@NotNull Modifier chargesMax); + + void setChargesFuel(@Nullable ItemStack chargesFuel); + + @NotNull Modifier getChargesConsumeAmount(); + + void setChargesConsumeAmount(@NotNull Modifier chargesConsumeAmount); + + @NotNull Modifier getChargesRechargeAmount(); + + void setChargesRechargeAmount(@NotNull Modifier chargesRechargeAmount); +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/IEnchantment.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/IEnchantment.java deleted file mode 100644 index 391d5db..0000000 --- a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/IEnchantment.java +++ /dev/null @@ -1,94 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment; - -import org.bukkit.Keyed; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JYML; - -import java.util.List; -import java.util.Set; - -public interface IEnchantment extends Keyed { - - boolean isAvailableToUse(@NotNull LivingEntity entity); - - @NotNull JYML getConfig(); - - @NotNull String getId(); - - @NotNull String getDisplayName(); - - @NotNull String getNameFormatted(int level); - - @NotNull String getNameFormatted(int level, int charges); - - @NotNull List getDescription(); - - @NotNull List getDescription(int level); - - @NotNull Set getConflicts(); - - @NotNull ITier getTier(); - - @NotNull EnchantmentTarget getCategory(); - - ItemCategory[] getFitItemTypes(); - - int getMaxLevel(); - - int getStartLevel(); - - int getLevelByEnchantCost(int expLevel); - - double getObtainChance(@NotNull ObtainType obtainType); - - int getObtainLevelMin(@NotNull ObtainType obtainType); - - int getObtainLevelMax(@NotNull ObtainType obtainType); - - int generateLevel(@NotNull ObtainType obtainType); - - int getAnvilMergeCost(int level); - - //@Deprecated - //boolean conflictsWith(@NotNull Enchantment enchantment); - - boolean checkEnchantCategory(@NotNull ItemStack item); - - boolean checkItemCategory(@NotNull ItemStack item); - - boolean isCurse(); - - boolean isTreasure(); - - boolean isTradeable(); - - boolean isDiscoverable(); - - boolean isChargesEnabled(); - - int getChargesMax(int level); - - int getChargesConsumeAmount(int level); - - int getChargesRechargeAmount(int level); - - @NotNull ItemStack getChargesFuel(); - - boolean isChargesFuel(@NotNull ItemStack item); - - int getCharges(@NotNull ItemStack item); - - boolean isFullOfCharges(@NotNull ItemStack item); - - boolean isOutOfCharges(@NotNull ItemStack item); - - void consumeCharges(@NotNull ItemStack item, int level); - - void consumeChargesNoUpdate(@NotNull ItemStack item, int level); - - EquipmentSlot[] getSlots(); -} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ITier.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ITier.java deleted file mode 100644 index 23d34ef..0000000 --- a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ITier.java +++ /dev/null @@ -1,21 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment; - -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.placeholder.Placeholder; - -import java.util.Map; - -public interface ITier extends Placeholder { - - @NotNull String getId(); - - int getPriority(); - - @NotNull String getName(); - - @NotNull String getColor(); - - @NotNull Map getChance(); - - double getChance(@NotNull ObtainType obtainType); -} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ItemCategory.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ItemCategory.java index 05c73fb..047fd82 100644 --- a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ItemCategory.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/ItemCategory.java @@ -3,7 +3,7 @@ package su.nightexpress.excellentenchants.api.enchantment; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.ItemUtil; +import su.nightexpress.nightcore.util.ItemUtil; import java.util.function.Predicate; @@ -24,6 +24,7 @@ public enum ItemCategory { PICKAXE(ItemUtil::isPickaxe), SHOVEL(ItemUtil::isShovel), FISHING_ROD(ItemUtil::isFishingRod), + SHIELD(itemStack -> itemStack.getType() == Material.SHIELD), //@Deprecated WEAPON(item -> SWORD.isIncluded(item) || TRIDENT.isIncluded(item)), TOOL(ItemUtil::isTool), @@ -46,83 +47,7 @@ public enum ItemCategory { this.predicate = predicate; } - @Deprecated - public void patchPredicate(@NotNull Predicate extra) { - //this.setPredicate(item -> this.getPredicate().test(item) || (extra.test(item))); - } - - /*public EquipmentSlot[] getSlots() { - return switch (this) { - case BOW, CROSSBOW, TRIDENT, FISHING_ROD, WEAPON, TOOL, HOE, PICKAXE, AXE, SWORD, SHOVEL -> - new EquipmentSlot[]{EquipmentSlot.HAND}; - case HELMET -> new EquipmentSlot[]{EquipmentSlot.HEAD}; - case CHESTPLATE, ELYTRA -> new EquipmentSlot[]{EquipmentSlot.CHEST}; - case LEGGINGS -> new EquipmentSlot[]{EquipmentSlot.LEGS}; - case BOOTS -> new EquipmentSlot[]{EquipmentSlot.FEET}; - case ARMOR -> new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; - case UNIVERSAL -> new EquipmentSlot[]{EquipmentSlot.HAND, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; - }; - } - - @NotNull - public EnchantmentTarget getEnchantmentTarget() { - return switch (this) { - case ARMOR -> EnchantmentTarget.ARMOR; - case BOOTS -> EnchantmentTarget.ARMOR_FEET; - case LEGGINGS -> EnchantmentTarget.ARMOR_LEGS; - case CHESTPLATE, ELYTRA -> EnchantmentTarget.ARMOR_TORSO; - case HELMET -> EnchantmentTarget.ARMOR_HEAD; - case WEAPON, SWORD -> EnchantmentTarget.WEAPON; - case TOOL, AXE, HOE, SHOVEL, PICKAXE -> EnchantmentTarget.TOOL; - case BOW -> EnchantmentTarget.BOW; - case FISHING_ROD -> EnchantmentTarget.FISHING_ROD; - case TRIDENT -> EnchantmentTarget.TRIDENT; - case CROSSBOW -> EnchantmentTarget.CROSSBOW; - case UNIVERSAL -> EnchantmentTarget.WEARABLE; - }; - } - - @NotNull - public static FitItemType getByEnchantmentTarget(@NotNull EnchantmentTarget target) { - return switch (target) { - case ARMOR -> ARMOR; - case ARMOR_FEET -> BOOTS; - case ARMOR_LEGS -> LEGGINGS; - case ARMOR_TORSO -> CHESTPLATE; - case ARMOR_HEAD -> HELMET; - case WEAPON -> WEAPON; - case TOOL -> TOOL; - case BOW -> BOW; - case FISHING_ROD -> FISHING_ROD; - case TRIDENT -> TRIDENT; - case CROSSBOW -> CROSSBOW; - case BREAKABLE, WEARABLE -> UNIVERSAL; - default -> throw new IllegalStateException("Unexpected value: " + target); - }; - }*/ - public boolean isIncluded(@NotNull ItemStack item) { return this.getPredicate().test(item); - - /*return switch (this) { - case UNIVERSAL -> ARMOR.isIncluded(item) || WEAPON.isIncluded(item) || TOOL.isIncluded(item) || BOW.isIncluded(item) || FISHING_ROD.isIncluded(item) || ELYTRA.isIncluded(item); - case HELMET -> ItemUtil.isHelmet(item); - case CHESTPLATE -> ItemUtil.isChestplate(item) || (Config.ENCHANTMENTS_ITEM_CHESTPLATE_ENCHANTS_TO_ELYTRA.get() && ELYTRA.isIncluded(item)); - case LEGGINGS -> ItemUtil.isLeggings(item); - case BOOTS -> ItemUtil.isBoots(item); - case ELYTRA -> item.getType() == Material.ELYTRA; - case WEAPON -> SWORD.isIncluded(item) || ItemUtil.isTrident(item); - case TOOL -> ItemUtil.isTool(item); - case ARMOR -> ItemUtil.isArmor(item); - case SWORD -> ItemUtil.isSword(item) || (Config.ENCHANTMENTS_ITEM_SWORD_ENCHANTS_TO_AXES.get() && AXE.isIncluded(item)); - case TRIDENT -> ItemUtil.isTrident(item); - case AXE -> ItemUtil.isAxe(item); - case BOW -> item.getType() == Material.BOW || (Config.ENCHANTMENTS_ITEM_BOW_ENCHANTS_TO_CROSSBOW.get() && CROSSBOW.isIncluded(item)); - case CROSSBOW -> item.getType() == Material.CROSSBOW; - case HOE -> ItemUtil.isHoe(item); - case PICKAXE -> ItemUtil.isPickaxe(item); - case SHOVEL -> ItemUtil.isShovel(item); - case FISHING_ROD -> item.getType() == Material.FISHING_ROD; - };*/ } } diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Rarity.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Rarity.java index 1725955..add23a7 100644 --- a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Rarity.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Rarity.java @@ -1,5 +1,11 @@ package su.nightexpress.excellentenchants.api.enchantment; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.util.random.Rnd; + +import java.util.HashMap; +import java.util.Map; + public enum Rarity { COMMON(10), @@ -7,7 +13,7 @@ public enum Rarity { RARE(2), VERY_RARE(1); - private final int weight; + private int weight; Rarity(int weight) { this.weight = weight; @@ -16,4 +22,19 @@ public enum Rarity { public int getWeight() { return this.weight; } + + public void setWeight(int weight) { + this.weight = weight; + } + + @NotNull + public static Rarity getByWeight() { + Map map = new HashMap<>(); + + for (Rarity rarity : Rarity.values()) { + map.put(rarity, (double) rarity.getWeight()); + } + + return Rnd.getByWeight(map); + } } diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ArrowData.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ArrowData.java new file mode 100644 index 0000000..9e41d5d --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ArrowData.java @@ -0,0 +1,14 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +public interface ArrowData { + + @NotNull ArrowSettings getArrowSettings(); + + @NotNull + default UniParticle getProjectileTrail() { + return this.getArrowSettings().getProjectileTrail(); + } +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ArrowSettings.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ArrowSettings.java new file mode 100644 index 0000000..2be85b5 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ArrowSettings.java @@ -0,0 +1,9 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +public interface ArrowSettings { + + @NotNull UniParticle getProjectileTrail(); +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Chanced.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ChanceData.java similarity index 54% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Chanced.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ChanceData.java index 21f2b32..3017045 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Chanced.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ChanceData.java @@ -1,10 +1,10 @@ -package su.nightexpress.excellentenchants.api.enchantment.meta; +package su.nightexpress.excellentenchants.api.enchantment.data; import org.jetbrains.annotations.NotNull; -public interface Chanced { +public interface ChanceData { - @NotNull Chanced getChanceImplementation(); + @NotNull ChanceSettings getChanceSettings(); /*@NotNull default UnaryOperator replacePlaceholders(int level) { @@ -12,10 +12,10 @@ public interface Chanced { }*/ default double getTriggerChance(int level) { - return this.getChanceImplementation().getTriggerChance(level); + return this.getChanceSettings().getTriggerChance(level); } default boolean checkTriggerChance(int level) { - return getChanceImplementation().checkTriggerChance(level); + return getChanceSettings().checkTriggerChance(level); } } diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ChanceSettings.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ChanceSettings.java new file mode 100644 index 0000000..b15dac8 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/ChanceSettings.java @@ -0,0 +1,8 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +public interface ChanceSettings { + + double getTriggerChance(int level); + + boolean checkTriggerChance(int level); +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PeriodicData.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PeriodicData.java new file mode 100644 index 0000000..e92a5e2 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PeriodicData.java @@ -0,0 +1,24 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +import org.jetbrains.annotations.NotNull; + +public interface PeriodicData { + + @NotNull PeriodicSettings getPeriodSettings(); + + default long getInterval() { + return this.getPeriodSettings().getInterval(); + } + + default long getNextTriggerTime() { + return this.getPeriodSettings().getNextTriggerTime(); + } + + default boolean isTriggerTime() { + return this.getPeriodSettings().isTriggerTime(); + } + + default void updateTriggerTime() { + this.getPeriodSettings().updateTriggerTime(); + } +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PeriodicSettings.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PeriodicSettings.java new file mode 100644 index 0000000..31cfad9 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PeriodicSettings.java @@ -0,0 +1,12 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +public interface PeriodicSettings { + + long getInterval(); + + long getNextTriggerTime(); + + boolean isTriggerTime(); + + void updateTriggerTime(); +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PotionData.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PotionData.java new file mode 100644 index 0000000..a747352 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PotionData.java @@ -0,0 +1,35 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; + +public interface PotionData { + + @NotNull PotionSettings getPotionSettings(); + + default boolean isPermanent() { + return this.getPotionSettings().isPermanent(); + } + + default PotionEffectType getEffectType() { + return this.getPotionSettings().getEffectType(); + } + + default int getEffectAmplifier(int level) { + return this.getPotionSettings().getEffectAmplifier(level); + } + + default int getEffectDuration(int level) { + return this.getPotionSettings().getEffectDuration(level); + } + + default PotionEffect createEffect(int level) { + return this.getPotionSettings().createEffect(level); + } + + default boolean addEffect(@NotNull LivingEntity target, int level) { + return this.getPotionSettings().addEffect(target, level); + } +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PotionSettings.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PotionSettings.java new file mode 100644 index 0000000..727bea2 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/data/PotionSettings.java @@ -0,0 +1,21 @@ +package su.nightexpress.excellentenchants.api.enchantment.data; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; + +public interface PotionSettings { + + boolean isPermanent(); + + PotionEffectType getEffectType(); + + int getEffectAmplifier(int level); + + int getEffectDuration(int level); + + PotionEffect createEffect(int level); + + boolean addEffect(@NotNull LivingEntity target, int level); +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/distribution/DistributionOptions.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/distribution/DistributionOptions.java new file mode 100644 index 0000000..84d9174 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/distribution/DistributionOptions.java @@ -0,0 +1,9 @@ +package su.nightexpress.excellentenchants.api.enchantment.distribution; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.config.FileConfig; + +public interface DistributionOptions { + + void load(@NotNull FileConfig config); +} diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/distribution/VanillaOptions.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/distribution/VanillaOptions.java new file mode 100644 index 0000000..14be8c9 --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/distribution/VanillaOptions.java @@ -0,0 +1,12 @@ +package su.nightexpress.excellentenchants.api.enchantment.distribution; + +public interface VanillaOptions extends DistributionOptions { + + boolean isDiscoverable(); + + void setDiscoverable(boolean discoverable); + + boolean isTradeable(); + + void setTradeable(boolean tradeable); +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockBreakEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockBreakEnchant.java similarity index 78% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockBreakEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockBreakEnchant.java index 32de3aa..58d6ebd 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockBreakEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockBreakEnchant.java @@ -5,9 +5,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface BlockBreakEnchant extends IEnchantment { +public interface BlockBreakEnchant extends EnchantmentData { boolean onBreak(@NotNull BlockBreakEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockDropEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockDropEnchant.java similarity index 78% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockDropEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockDropEnchant.java index e8c3268..7522603 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockDropEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BlockDropEnchant.java @@ -5,9 +5,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockDropItemEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface BlockDropEnchant extends IEnchantment { +public interface BlockDropEnchant extends EnchantmentData { boolean onDrop(@NotNull BlockDropItemEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BowEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BowEnchant.java similarity index 90% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BowEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BowEnchant.java index 4653606..b5c5f16 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BowEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/BowEnchant.java @@ -8,9 +8,9 @@ import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface BowEnchant extends IEnchantment { +public interface BowEnchant extends EnchantmentData { boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/CombatEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/CombatEnchant.java similarity index 87% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/CombatEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/CombatEnchant.java index 54e9535..d298def 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/CombatEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/CombatEnchant.java @@ -5,9 +5,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface CombatEnchant extends IEnchantment { +public interface CombatEnchant extends EnchantmentData { boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DamageEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DamageEnchant.java similarity index 79% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DamageEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DamageEnchant.java index 8099f3f..beca835 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DamageEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DamageEnchant.java @@ -5,9 +5,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface DamageEnchant extends IEnchantment { +public interface DamageEnchant extends EnchantmentData { boolean onDamage(@NotNull EntityDamageEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DeathEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DeathEnchant.java similarity index 87% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DeathEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DeathEnchant.java index e961ccc..97be5c7 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DeathEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/DeathEnchant.java @@ -7,9 +7,9 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface DeathEnchant extends IEnchantment { +public interface DeathEnchant extends EnchantmentData { boolean onDeath(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, ItemStack item, int level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/FishingEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/FishingEnchant.java similarity index 76% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/FishingEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/FishingEnchant.java index cc45db4..69b91ea 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/FishingEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/FishingEnchant.java @@ -4,9 +4,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface FishingEnchant extends IEnchantment { +public interface FishingEnchant extends EnchantmentData { boolean onFishing(@NotNull PlayerFishEvent event, @NotNull ItemStack item, int level); diff --git a/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/GenericEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/GenericEnchant.java new file mode 100644 index 0000000..4d37a3b --- /dev/null +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/GenericEnchant.java @@ -0,0 +1,7 @@ +package su.nightexpress.excellentenchants.api.enchantment.type; + +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; + +public interface GenericEnchant extends EnchantmentData { + +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/InteractEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/InteractEnchant.java similarity index 79% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/InteractEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/InteractEnchant.java index e4e526c..57e2fc6 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/InteractEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/InteractEnchant.java @@ -5,9 +5,9 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; -public interface InteractEnchant extends IEnchantment { +public interface InteractEnchant extends EnchantmentData { boolean onInteract(@NotNull PlayerInteractEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/PassiveEnchant.java b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/PassiveEnchant.java similarity index 55% rename from Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/PassiveEnchant.java rename to API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/PassiveEnchant.java index 28c190d..c9ce7af 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/PassiveEnchant.java +++ b/API/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/PassiveEnchant.java @@ -3,10 +3,10 @@ package su.nightexpress.excellentenchants.api.enchantment.type; import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; -import su.nightexpress.excellentenchants.api.enchantment.meta.Periodic; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicData; -public interface PassiveEnchant extends IEnchantment, Periodic { +public interface PassiveEnchant extends EnchantmentData, PeriodicData { boolean onTrigger(@NotNull LivingEntity entity, @NotNull ItemStack item, int level); } diff --git a/Core/pom.xml b/Core/pom.xml index ac556bf..3cb4530 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -5,15 +5,16 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 Core - 16 - 16 + 17 + 17 + UTF-8 @@ -54,7 +55,7 @@ io.lumine Mythic-Dist - 5.0.1-SNAPSHOT + 5.6.0-SNAPSHOT provided @@ -72,37 +73,32 @@ su.nightexpress.excellentenchants API - 3.6.5 + 4.0.0 su.nightexpress.excellentenchants NMS - 3.6.5 - - - su.nightexpress.excellentenchants - V1_18_R2 - 3.6.5 + 4.0.0 su.nightexpress.excellentenchants V1_19_R3 - 3.6.5 + 4.0.0 su.nightexpress.excellentenchants V1_20_R1 - 3.6.5 + 4.0.0 su.nightexpress.excellentenchants V1_20_R2 - 3.6.5 + 4.0.0 su.nightexpress.excellentenchants V1_20_R3 - 3.6.5 + 4.0.0 diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchantsAPI.java b/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchantsAPI.java deleted file mode 100644 index a7ccda1..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchantsAPI.java +++ /dev/null @@ -1,20 +0,0 @@ -package su.nightexpress.excellentenchants; - -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.enchantment.EnchantManager; -import su.nightexpress.excellentenchants.tier.TierManager; - -public class ExcellentEnchantsAPI { - - public static final ExcellentEnchants PLUGIN = ExcellentEnchants.getPlugin(ExcellentEnchants.class); - - @NotNull - public static EnchantManager getEnchantManager() { - return PLUGIN.getEnchantManager(); - } - - @NotNull - public static TierManager getTierManager() { - return PLUGIN.getTierManager(); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchants.java b/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchantsPlugin.java similarity index 60% rename from Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchants.java rename to Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchantsPlugin.java index b875dc9..06d9881 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchants.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/ExcellentEnchantsPlugin.java @@ -1,20 +1,19 @@ package su.nightexpress.excellentenchants; import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.Item; +import org.bukkit.event.block.BlockDropItemEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.NexPlugin; -import su.nexmedia.engine.Version; -import su.nexmedia.engine.api.command.GeneralCommand; -import su.nexmedia.engine.command.list.ReloadSubCommand; -import su.nexmedia.engine.utils.EngineUtils; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.command.BookCommand; import su.nightexpress.excellentenchants.command.EnchantCommand; import su.nightexpress.excellentenchants.command.ListCommand; -import su.nightexpress.excellentenchants.command.TierbookCommand; +import su.nightexpress.excellentenchants.command.RarityBookCommand; import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.config.Keys; import su.nightexpress.excellentenchants.config.Lang; import su.nightexpress.excellentenchants.enchantment.EnchantManager; import su.nightexpress.excellentenchants.enchantment.EnchantPopulator; @@ -23,38 +22,38 @@ import su.nightexpress.excellentenchants.hook.HookId; import su.nightexpress.excellentenchants.hook.impl.PlaceholderHook; import su.nightexpress.excellentenchants.hook.impl.ProtocolHook; import su.nightexpress.excellentenchants.nms.EnchantNMS; -import su.nightexpress.excellentenchants.nms.v1_18_R2.V1_18_R2; import su.nightexpress.excellentenchants.nms.v1_19_R3.V1_19_R3; import su.nightexpress.excellentenchants.nms.v1_20_R1.V1_20_R1; import su.nightexpress.excellentenchants.nms.v1_20_R2.V1_20_R2; import su.nightexpress.excellentenchants.nms.v1_20_R3.V1_20_R3; -import su.nightexpress.excellentenchants.tier.TierManager; +import su.nightexpress.nightcore.NightPlugin; +import su.nightexpress.nightcore.command.api.NightPluginCommand; +import su.nightexpress.nightcore.command.base.ReloadSubCommand; +import su.nightexpress.nightcore.config.PluginDetails; +import su.nightexpress.nightcore.util.Plugins; +import su.nightexpress.nightcore.util.Version; -public class ExcellentEnchants extends NexPlugin { - - // TODO Config option to use minecraft internal enchanting population - // TODO Custom name format for curse enchants - // TODO Custom name format for treasure enchants +public class ExcellentEnchantsPlugin extends NightPlugin { private EnchantRegistry registry; private EnchantManager enchantManager; private EnchantNMS enchantNMS; - private TierManager tierManager; - - @Override - @NotNull - protected ExcellentEnchants getSelf() { - return this; - } @Override public void onLoad() { super.onLoad(); - - //this.updateFitItemTypes(); this.registry = new EnchantRegistry(this); } + @Override + @NotNull + protected PluginDetails getDefaultDetails() { + return PluginDetails.create("Enchants", new String[]{"excellentenchants", "eenchants"}) + .setConfigClass(Config.class) + .setLangClass(Lang.class) + .setPermissionsClass(Perms.class); + } + @Override public void enable() { if (!this.setNMS()) { @@ -63,8 +62,15 @@ public class ExcellentEnchants extends NexPlugin { return; } - this.tierManager = new TierManager(this); - this.tierManager.setup(); + Keys.loadKeys(this); + Config.loadRarityWeights(this.getConfig()); + + this.getLangManager().loadEnum(ItemCategory.class); + this.getLangManager().loadEnum(EnchantmentTarget.class); + this.getLangManager().loadEnum(DistributionWay.class); + this.getLangManager().loadEnum(Rarity.class); + + this.registerCommands(); this.registry.setup(); @@ -72,14 +78,18 @@ public class ExcellentEnchants extends NexPlugin { this.enchantManager.setup(); if (Config.ENCHANTMENTS_DISPLAY_MODE.get() == 2) { - if (EngineUtils.hasPlugin(HookId.PROTOCOL_LIB)) { - ProtocolHook.setup(); + if (Plugins.isInstalled(HookId.PROTOCOL_LIB)) { + ProtocolHook.setup(this); } else { - this.warn(HookId.PROTOCOL_LIB + " is not installed. Set display mode to Plain lore."); + this.warn(HookId.PROTOCOL_LIB + " is not installed. Display mode is set to Plain lore."); Config.ENCHANTMENTS_DISPLAY_MODE.set(1); } } + + if (Plugins.hasPlaceholderAPI()) { + PlaceholderHook.setup(this); + } } @Override @@ -88,19 +98,16 @@ public class ExcellentEnchants extends NexPlugin { this.enchantManager.shutdown(); this.enchantManager = null; } - if (this.tierManager != null) { - this.tierManager.shutdown(); - this.tierManager = null; - } - if (EngineUtils.hasPlaceholderAPI()) { + + if (Plugins.hasPlaceholderAPI()) { PlaceholderHook.shutdown(); } + this.registry.shutdown(); } private boolean setNMS() { this.enchantNMS = switch (Version.getCurrent()) { - case V1_18_R2 -> new V1_18_R2(); case V1_19_R3 -> new V1_19_R3(); case V1_20_R1 -> new V1_20_R1(); case V1_20_R2 -> new V1_20_R2(); @@ -110,49 +117,27 @@ public class ExcellentEnchants extends NexPlugin { return this.enchantNMS != null; } - @Override - public void loadConfig() { - this.getConfig().initializeOptions(Config.class); - } - - @Override - public void loadLang() { - this.getLangManager().loadMissing(Lang.class); - this.getLangManager().loadEnum(ItemCategory.class); - this.getLangManager().loadEnum(EnchantmentTarget.class); - this.getLangManager().loadEnum(ObtainType.class); - this.getLang().saveChanges(); - } - - @Override - public void registerCommands(@NotNull GeneralCommand mainCommand) { + private void registerCommands() { + NightPluginCommand mainCommand = this.getBaseCommand(); mainCommand.addChildren(new BookCommand(this)); mainCommand.addChildren(new EnchantCommand(this)); mainCommand.addChildren(new ListCommand(this)); - mainCommand.addChildren(new TierbookCommand(this)); - mainCommand.addChildren(new ReloadSubCommand<>(this, Perms.COMMAND_RELOAD)); - } - - @Override - public void registerHooks() { - if (EngineUtils.hasPlaceholderAPI()) { - PlaceholderHook.setup(this); - } - } - - @Override - public void registerPermissions() { - this.registerPermissions(Perms.class); + mainCommand.addChildren(new RarityBookCommand(this)); + mainCommand.addChildren(new ReloadSubCommand(this, Perms.COMMAND_RELOAD)); } @NotNull - public EnchantPopulator createPopulator(@NotNull ItemStack item, @NotNull ObtainType obtainType) { - return new EnchantPopulator(this, item, obtainType); + public EnchantPopulator createPopulator(@NotNull ItemStack item, @NotNull DistributionWay distributionWay) { + return new EnchantPopulator(this, item, distributionWay); } - @NotNull - public TierManager getTierManager() { - return tierManager; + public void populateResource(@NotNull BlockDropItemEvent event, @NotNull ItemStack itemStack) { + /*if (Plugins.isSpigot()) { + this.warn("Adding items to BlockDropItemEvent is not supported in Spigot, please use Paper or its forks for this feature."); + return; + }*/ + Item item = this.getEnchantNMS().popResource(event.getBlock(), itemStack); + event.getItems().add(item); } @NotNull diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/Perms.java b/Core/src/main/java/su/nightexpress/excellentenchants/Perms.java index 88045d3..f11ffe2 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/Perms.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/Perms.java @@ -1,25 +1,31 @@ package su.nightexpress.excellentenchants; import org.bukkit.permissions.PermissionDefault; -import su.nexmedia.engine.api.server.JPermission; +import su.nightexpress.nightcore.util.wrapper.UniPermission; public class Perms { - private static final String PREFIX = "excellentenchants."; + private static final String PREFIX = "excellentenchants."; private static final String PREFIX_COMMAND = PREFIX + "command."; - public static final JPermission PLUGIN = new JPermission(PREFIX + Placeholders.WILDCARD, "Access to all the plugin functions."); - public static final JPermission COMMAND = new JPermission(PREFIX_COMMAND + Placeholders.WILDCARD, "Access to all the plugin commands."); + public static final UniPermission PLUGIN = new UniPermission(PREFIX + Placeholders.WILDCARD, "Access to all the plugin functions."); + public static final UniPermission COMMAND = new UniPermission(PREFIX_COMMAND + Placeholders.WILDCARD, "Access to all the plugin commands."); - public static final JPermission COMMAND_BOOK = new JPermission(PREFIX_COMMAND + "book", "Allows to use '/eenchants book' command."); - public static final JPermission COMMAND_ENCHANT = new JPermission(PREFIX_COMMAND + "enchant", "Allows to use '/eenchants enchant' command."); - public static final JPermission COMMAND_LIST = new JPermission(PREFIX_COMMAND + "list", "Allows to use '/eenchants list' command.", PermissionDefault.TRUE); - public static final JPermission COMMAND_TIERBOOK = new JPermission(PREFIX_COMMAND + "tierbook", "Allows to use '/eenchants tierbook' command."); - public static final JPermission COMMAND_RELOAD = new JPermission(PREFIX_COMMAND + "reload", "Allows to use '/eenchants reload' command."); + public static final UniPermission COMMAND_BOOK = new UniPermission(PREFIX_COMMAND + "book"); + public static final UniPermission COMMAND_ENCHANT = new UniPermission(PREFIX_COMMAND + "enchant"); + public static final UniPermission COMMAND_LIST = new UniPermission(PREFIX_COMMAND + "list", "Allows to use '/eenchants list' command.", PermissionDefault.TRUE); + public static final UniPermission COMMAND_RARITY_BOOK = new UniPermission(PREFIX_COMMAND + "raritybook"); + public static final UniPermission COMMAND_RELOAD = new UniPermission(PREFIX_COMMAND + "reload"); static { PLUGIN.addChildren(COMMAND); - COMMAND.addChildren(COMMAND_BOOK, COMMAND_ENCHANT, COMMAND_LIST, COMMAND_RELOAD, COMMAND_TIERBOOK); + COMMAND.addChildren( + COMMAND_BOOK, + COMMAND_ENCHANT, + COMMAND_LIST, + COMMAND_RELOAD, + COMMAND_RARITY_BOOK + ); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/Placeholders.java b/Core/src/main/java/su/nightexpress/excellentenchants/Placeholders.java index 03b4bc5..e07c99e 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/Placeholders.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/Placeholders.java @@ -1,54 +1,56 @@ -/* - * Decompiled with CFR 0.151. - * - * Could not load the following classes: - * su.nexmedia.engine.utils.Placeholders - */ package su.nightexpress.excellentenchants; -public class Placeholders -extends su.nexmedia.engine.utils.Placeholders { - public static final String URL_WIKI = "https://github.com/nulli0n/ExcellentEnchants-spigot/wiki/"; +public class Placeholders extends su.nightexpress.nightcore.util.Placeholders { + + public static final String URL_WIKI = "https://github.com/nulli0n/ExcellentEnchants-spigot/wiki/"; public static final String URL_PLACEHOLDERS = "https://github.com/nulli0n/ExcellentEnchants-spigot/wiki/Internal-Placeholders"; - public static final String URL_ENGINE_SCALER = "https://github.com/nulli0n/NexEngine-spigot/wiki/Configuration-Tips#scalable-sections"; - public static final String URL_ENGINE_ITEMS = "https://github.com/nulli0n/NexEngine-spigot/wiki/Configuration-Tips#item-sections"; - public static final String GENERIC_TYPE = "%type%"; - public static final String GENERIC_NAME = "%name%"; - public static final String GENERIC_ITEM = "%item%"; - public static final String GENERIC_LEVEL = "%level%"; - public static final String GENERIC_AMOUNT = "%amount%"; + public static final String URL_CHRAGES = "https://github.com/nulli0n/ExcellentEnchants-spigot/wiki/Charges-System"; + + public static final String VANILLA_DISTRIBUTION_NAME = "Vanilla Distribution Mode"; + public static final String CUSTOM_DISTRIBUTION_NAME = "Custom Distribution Mode"; + + public static final String VANILLA_DISTRIBUTION_HEADER = "=".repeat(15) + " " + VANILLA_DISTRIBUTION_NAME + " " + "=".repeat(15); + public static final String CUSTOM_DISTRIBUTION_HEADER = "=".repeat(15) + " " + CUSTOM_DISTRIBUTION_NAME + " " + "=".repeat(15); + + public static final String GENERIC_TYPE = "%type%"; + public static final String GENERIC_NAME = "%name%"; + public static final String GENERIC_ITEM = "%item%"; + public static final String GENERIC_LEVEL = "%level%"; + public static final String GENERIC_AMOUNT = "%amount%"; public static final String GENERIC_DESCRIPTION = "%description%"; - public static final String GENERIC_ENCHANT = "%enchant%"; - public static final String ENCHANTMENT_CHANCE = "%enchantment_trigger_chance%"; - public static final String ENCHANTMENT_INTERVAL = "%enchantment_trigger_interval%"; - public static final String ENCHANTMENT_POTION_LEVEL = "%enchantment_potion_level%"; - public static final String ENCHANTMENT_POTION_DURATION = "%enchantment_potion_duration%"; - public static final String ENCHANTMENT_POTION_TYPE = "%enchantment_potion_type%"; - public static final String ENCHANTMENT_ID = "%enchantment_id%"; - public static final String ENCHANTMENT_NAME = "%enchantment_name%"; - public static final String ENCHANTMENT_NAME_FORMATTED = "%enchantment_name_formatted%"; - public static final String ENCHANTMENT_DESCRIPTION = "%enchantment_description%"; - public static final String ENCHANTMENT_LEVEL = "%enchantment_level%"; - public static final String ENCHANTMENT_LEVEL_MIN = "%enchantment_level_min%"; - public static final String ENCHANTMENT_LEVEL_MAX = "%enchantment_level_max%"; - public static final String ENCHANTMENT_TIER = "%enchantment_tier%"; - public static final String ENCHANTMENT_TIER_COLOR = "%enchantment_tier_color%"; - public static final String ENCHANTMENT_FIT_ITEM_TYPES = "%enchantment_fit_item_types%"; - public static final String ENCHANTMENT_OBTAIN_CHANCE_ENCHANTING = "%enchantment_obtain_chance_enchanting%"; - public static final String ENCHANTMENT_OBTAIN_CHANCE_VILLAGER = "%enchantment_obtain_chance_villager%"; + public static final String GENERIC_ENCHANT = "%enchant%"; + public static final String GENERIC_RADIUS = "%radius%"; + public static final String GENERIC_DURATION = "%duration%"; + public static final String GENERIC_DAMAGE = "%damage%"; + public static final String GENERIC_MIN = "%min%"; + public static final String GENERIC_MAX = "%max%"; + public static final String GENERIC_TIME = "%time%"; + + public static final String ENCHANTMENT_CHANCE = "%enchantment_trigger_chance%"; + public static final String ENCHANTMENT_INTERVAL = "%enchantment_trigger_interval%"; + public static final String ENCHANTMENT_POTION_LEVEL = "%enchantment_potion_level%"; + public static final String ENCHANTMENT_POTION_DURATION = "%enchantment_potion_duration%"; + public static final String ENCHANTMENT_POTION_TYPE = "%enchantment_potion_type%"; + public static final String ENCHANTMENT_ID = "%enchantment_id%"; + public static final String ENCHANTMENT_NAME = "%enchantment_name%"; + public static final String ENCHANTMENT_NAME_FORMATTED = "%enchantment_name_formatted%"; + public static final String ENCHANTMENT_DESCRIPTION = "%enchantment_description%"; + public static final String ENCHANTMENT_DESCRIPTION_FORMATTED = "%enchantment_description_formatted%"; + public static final String ENCHANTMENT_DESCRIPTION_REPLACED = "%enchantment_description_replaced%"; + public static final String ENCHANTMENT_LEVEL = "%enchantment_level%"; + public static final String ENCHANTMENT_LEVEL_MIN = "%enchantment_level_min%"; + public static final String ENCHANTMENT_LEVEL_MAX = "%enchantment_level_max%"; + public static final String ENCHANTMENT_RARITY = "%enchantment_rarity%"; + public static final String ENCHANTMENT_FIT_ITEM_TYPES = "%enchantment_fit_item_types%"; + public static final String ENCHANTMENT_OBTAIN_CHANCE_ENCHANTING = "%enchantment_obtain_chance_enchanting%"; + public static final String ENCHANTMENT_OBTAIN_CHANCE_VILLAGER = "%enchantment_obtain_chance_villager%"; public static final String ENCHANTMENT_OBTAIN_CHANCE_LOOT_GENERATION = "%enchantment_obtain_chance_loot_generation%"; - public static final String ENCHANTMENT_OBTAIN_CHANCE_FISHING = "%enchantment_obtain_chance_fishing%"; - public static final String ENCHANTMENT_OBTAIN_CHANCE_MOB_SPAWNING = "%enchantment_obtain_chance_mob_spawning%"; - public static final String ENCHANTMENT_CHARGES_MAX_AMOUNT = "%enchantment_charges_max_amount%"; - public static final String ENCHANTMENT_CHARGES_CONSUME_AMOUNT = "%enchantment_charges_consume_amount%"; - public static final String ENCHANTMENT_CHARGES_RECHARGE_AMOUNT = "%enchantment_charges_recharge_amount%"; - public static final String ENCHANTMENT_CHARGES_FUEL_ITEM = "%enchantment_charges_fuel_item%"; - public static final String TIER_ID = "%tier_id%"; - public static final String TIER_NAME = "%tier_name%"; - public static final String TIER_OBTAIN_CHANCE_ENCHANTING = "%tier_obtain_chance_enchanting%"; - public static final String TIER_OBTAIN_CHANCE_VILLAGER = "%tier_obtain_chance_villager%"; - public static final String TIER_OBTAIN_CHANCE_LOOT_GENERATION = "%tier_obtain_chance_loot_generation%"; - public static final String TIER_OBTAIN_CHANCE_FISHING = "%tier_obtain_chance_fishing%"; - public static final String TIER_OBTAIN_CHANCE_MOB_SPAWNING = "%tier_obtain_chance_mob_spawning%"; + public static final String ENCHANTMENT_OBTAIN_CHANCE_FISHING = "%enchantment_obtain_chance_fishing%"; + public static final String ENCHANTMENT_OBTAIN_CHANCE_MOB_SPAWNING = "%enchantment_obtain_chance_mob_spawning%"; + public static final String ENCHANTMENT_CHARGES = "%enchantment_charges%"; + public static final String ENCHANTMENT_CHARGES_MAX_AMOUNT = "%enchantment_charges_max_amount%"; + public static final String ENCHANTMENT_CHARGES_CONSUME_AMOUNT = "%enchantment_charges_consume_amount%"; + public static final String ENCHANTMENT_CHARGES_RECHARGE_AMOUNT = "%enchantment_charges_recharge_amount%"; + public static final String ENCHANTMENT_CHARGES_FUEL_ITEM = "%enchantment_charges_fuel_item%"; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Cleanable.java b/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Cleanable.java deleted file mode 100644 index 4cc9d59..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/Cleanable.java +++ /dev/null @@ -1,6 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment; - -public interface Cleanable { - - void clear(); -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/IEnchantment.java b/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/IEnchantment.java deleted file mode 100644 index df57cb2..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/IEnchantment.java +++ /dev/null @@ -1,83 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment; - -import org.bukkit.Keyed; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.api.config.JYML; -import su.nightexpress.excellentenchants.enchantment.type.ObtainType; -import su.nightexpress.excellentenchants.tier.Tier; - -import java.util.List; -import java.util.Set; - -public interface IEnchantment extends Keyed { - - boolean isAvailableToUse(@NotNull LivingEntity entity); - - @NotNull JYML getConfig(); - - @NotNull String getId(); - - @NotNull String getDisplayName(); - - @NotNull String getNameFormatted(int level); - - @NotNull String getNameFormatted(int level, int charges); - - @NotNull List getDescription(); - - @NotNull List getDescription(int level); - - @NotNull Set getConflicts(); - - @NotNull Tier getTier(); - - int getMaxLevel(); - - int getStartLevel(); - - int getLevelByEnchantCost(int expLevel); - - double getObtainChance(@NotNull ObtainType obtainType); - - int getObtainLevelMin(@NotNull ObtainType obtainType); - - int getObtainLevelMax(@NotNull ObtainType obtainType); - - int generateLevel(@NotNull ObtainType obtainType); - - int getAnvilMergeCost(int level); - - boolean conflictsWith(@NotNull Enchantment enchantment); - - boolean canEnchantItem(@Nullable ItemStack item); - - boolean isCursed(); - - boolean isTreasure(); - - boolean isChargesEnabled(); - - int getChargesMax(int level); - - int getChargesConsumeAmount(int level); - - int getChargesRechargeAmount(int level); - - @NotNull ItemStack getChargesFuel(); - - boolean isChargesFuel(@NotNull ItemStack item); - - int getCharges(@NotNull ItemStack item); - - boolean isFullOfCharges(@NotNull ItemStack item); - - boolean isOutOfCharges(@NotNull ItemStack item); - - void consumeCharges(@NotNull ItemStack item, int level); - - void consumeChargesNoUpdate(@NotNull ItemStack item, int level); -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Arrowed.java b/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Arrowed.java deleted file mode 100644 index d9ff04b..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Arrowed.java +++ /dev/null @@ -1,29 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment.meta; - -import org.bukkit.entity.Projectile; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; - -import java.util.Optional; - -public interface Arrowed { - - @NotNull Arrowed getArrowImplementation(); - - @NotNull - default Optional getTrailParticle() { - return this.getArrowImplementation().getTrailParticle(); - } - - default void addTrail(@NotNull Projectile projectile) { - this.getArrowImplementation().addTrail(projectile); - } - - default void addData(@NotNull Projectile projectile) { - this.getArrowImplementation().addData(projectile); - } - - default boolean isOurProjectile(@NotNull Projectile projectile) { - return this.getArrowImplementation().isOurProjectile(projectile); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Periodic.java b/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Periodic.java deleted file mode 100644 index f2194ce..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Periodic.java +++ /dev/null @@ -1,24 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment.meta; - -import org.jetbrains.annotations.NotNull; - -public interface Periodic { - - @NotNull Periodic getPeriodImplementation(); - - default long getInterval() { - return this.getPeriodImplementation().getInterval(); - } - - default long getNextTriggerTime() { - return this.getPeriodImplementation().getNextTriggerTime(); - } - - default boolean isTriggerTime() { - return this.getPeriodImplementation().isTriggerTime(); - } - - default void updateTriggerTime() { - this.getPeriodImplementation().updateTriggerTime(); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Potioned.java b/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Potioned.java deleted file mode 100644 index 246074a..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/meta/Potioned.java +++ /dev/null @@ -1,35 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment.meta; - -import org.bukkit.entity.LivingEntity; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; - -public interface Potioned { - - @NotNull Potioned getPotionImplementation(); - - default boolean isPermanent() { - return this.getPotionImplementation().isPermanent(); - } - - default PotionEffectType getEffectType() { - return this.getPotionImplementation().getEffectType(); - } - - default int getEffectAmplifier(int level) { - return this.getPotionImplementation().getEffectAmplifier(level); - } - - default int getEffectDuration(int level) { - return this.getPotionImplementation().getEffectDuration(level); - } - - default PotionEffect createEffect(int level) { - return this.getPotionImplementation().createEffect(level); - } - - default boolean addEffect(@NotNull LivingEntity target, int level) { - return this.getPotionImplementation().addEffect(target, level); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/GenericEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/GenericEnchant.java deleted file mode 100644 index f7aa000..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/api/enchantment/type/GenericEnchant.java +++ /dev/null @@ -1,7 +0,0 @@ -package su.nightexpress.excellentenchants.api.enchantment.type; - -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; - -public interface GenericEnchant extends IEnchantment { - -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/command/BookCommand.java b/Core/src/main/java/su/nightexpress/excellentenchants/command/BookCommand.java index a63f2f2..daa3ca4 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/command/BookCommand.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/command/BookCommand.java @@ -1,42 +1,41 @@ package su.nightexpress.excellentenchants.command; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.command.AbstractCommand; -import su.nexmedia.engine.api.command.CommandResult; -import su.nexmedia.engine.utils.CollectionsUtil; -import su.nexmedia.engine.utils.PlayerUtil; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.Perms; import su.nightexpress.excellentenchants.Placeholders; import su.nightexpress.excellentenchants.config.Lang; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.command.CommandResult; +import su.nightexpress.nightcore.command.impl.AbstractCommand; +import su.nightexpress.nightcore.util.BukkitThing; +import su.nightexpress.nightcore.util.Players; +import su.nightexpress.nightcore.util.random.Rnd; import java.util.Arrays; import java.util.List; -public class BookCommand extends AbstractCommand { +public class BookCommand extends AbstractCommand { - public BookCommand(@NotNull ExcellentEnchants plugin) { + public BookCommand(@NotNull ExcellentEnchantsPlugin plugin) { super(plugin, new String[]{"book"}, Perms.COMMAND_BOOK); - this.setDescription(plugin.getMessage(Lang.COMMAND_BOOK_DESC)); - this.setUsage(plugin.getMessage(Lang.COMMAND_BOOK_USAGE)); + this.setDescription(Lang.COMMAND_BOOK_DESC); + this.setUsage(Lang.COMMAND_BOOK_USAGE); } @Override @NotNull public List getTab(@NotNull Player player, int arg, @NotNull String[] args) { if (arg == 1) { - return CollectionsUtil.playerNames(player); + return Players.playerNames(player); } if (arg == 2) { - return Arrays.stream(Enchantment.values()).map(e -> e.getKey().getKey()).toList(); + return BukkitThing.getEnchantments().stream().map(enchantment -> enchantment.getKey().getKey()).toList(); } if (arg == 3) { return Arrays.asList("-1", "1", "5", "10"); @@ -47,19 +46,19 @@ public class BookCommand extends AbstractCommand { @Override protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) { if (result.length() < 4) { - this.printUsage(sender); + this.errorUsage(sender); return; } - Player player = PlayerUtil.getPlayer(result.getArg(1)); + Player player = Players.getPlayer(result.getArg(1)); if (player == null) { this.errorPlayer(sender); return; } - Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(result.getArg(2).toLowerCase())); + Enchantment enchantment = BukkitThing.getEnchantment(result.getArg(2)); if (enchantment == null) { - plugin.getMessage(Lang.ERROR_NO_ENCHANT).send(sender); + Lang.ERROR_NO_ENCHANT.getMessage().send(sender); return; } @@ -71,9 +70,9 @@ public class BookCommand extends AbstractCommand { ItemStack item = new ItemStack(Material.ENCHANTED_BOOK); EnchantUtils.add(item, enchantment, level, true); EnchantUtils.updateDisplay(item); - PlayerUtil.addItem(player, item); + Players.addItem(player, item); - plugin.getMessage(Lang.COMMAND_BOOK_DONE) + Lang.COMMAND_BOOK_DONE.getMessage() .replace(Placeholders.GENERIC_ENCHANT, EnchantUtils.getLocalized(enchantment)) .replace(Placeholders.forPlayer(player)) .send(sender); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/command/EnchantCommand.java b/Core/src/main/java/su/nightexpress/excellentenchants/command/EnchantCommand.java index 9d59d76..8665f44 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/command/EnchantCommand.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/command/EnchantCommand.java @@ -1,47 +1,46 @@ package su.nightexpress.excellentenchants.command; -import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.command.AbstractCommand; -import su.nexmedia.engine.api.command.CommandResult; -import su.nexmedia.engine.utils.*; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.Perms; import su.nightexpress.excellentenchants.Placeholders; import su.nightexpress.excellentenchants.config.Lang; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.command.CommandResult; +import su.nightexpress.nightcore.command.impl.AbstractCommand; +import su.nightexpress.nightcore.util.*; +import su.nightexpress.nightcore.util.random.Rnd; import java.util.Arrays; import java.util.List; -public class EnchantCommand extends AbstractCommand { +public class EnchantCommand extends AbstractCommand { - public EnchantCommand(@NotNull ExcellentEnchants plugin) { + public EnchantCommand(@NotNull ExcellentEnchantsPlugin plugin) { super(plugin, new String[]{"enchant"}, Perms.COMMAND_ENCHANT); - this.setDescription(plugin.getMessage(Lang.COMMAND_ENCHANT_DESC)); - this.setUsage(plugin.getMessage(Lang.COMMAND_ENCHANT_USAGE)); + this.setDescription(Lang.COMMAND_ENCHANT_DESC); + this.setUsage(Lang.COMMAND_ENCHANT_USAGE); } @Override @NotNull public List getTab(@NotNull Player player, int arg, @NotNull String[] args) { if (arg == 1) { - return Arrays.stream(Enchantment.values()).map(e -> e.getKey().getKey()).toList(); + return BukkitThing.getEnchantments().stream().map(enchantment -> enchantment.getKey().getKey()).toList(); } if (arg == 2) { return Arrays.asList("-1", "1", "5", "10"); } if (arg == 3) { - return CollectionsUtil.playerNames(player); + return Players.playerNames(player); } if (arg == 4) { - return CollectionsUtil.getEnumsList(EquipmentSlot.class); + return Lists.getEnums(EquipmentSlot.class); } return super.getTab(player, arg, args); } @@ -49,17 +48,17 @@ public class EnchantCommand extends AbstractCommand { @Override protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) { if (result.length() < 3) { - this.printUsage(sender); + this.errorUsage(sender); return; } - Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(result.getArg(1).toLowerCase())); + Enchantment enchantment = BukkitThing.getEnchantment(result.getArg(1)); if (enchantment == null) { - plugin.getMessage(Lang.ERROR_NO_ENCHANT).send(sender); + Lang.ERROR_NO_ENCHANT.getMessage().send(sender); return; } - Player player = PlayerUtil.getPlayer(result.getArg(3, sender.getName())); + Player player = Players.getPlayer(result.getArg(3, sender.getName())); if (player == null) { this.errorPlayer(sender); return; @@ -69,7 +68,7 @@ public class EnchantCommand extends AbstractCommand { ItemStack item = player.getInventory().getItem(slot); if (item == null || item.getType().isAir()) { - this.plugin.getMessage(Lang.COMMAND_ENCHANT_ERROR_NO_ITEM).send(sender); + Lang.COMMAND_ENCHANT_ERROR_NO_ITEM.getMessage().send(sender); return; } @@ -86,7 +85,7 @@ public class EnchantCommand extends AbstractCommand { EnchantUtils.updateDisplay(item); player.getInventory().setItem(slot, item); - plugin.getMessage(sender == player ? Lang.COMMAND_ENCHANT_DONE_SELF : Lang.COMMAND_ENCHANT_DONE_OTHERS) + (sender == player ? Lang.COMMAND_ENCHANT_DONE_SELF : Lang.COMMAND_ENCHANT_DONE_OTHERS).getMessage() .replace(Placeholders.forPlayer(player)) .replace(Placeholders.GENERIC_ITEM, ItemUtil.getItemName(item)) .replace(Placeholders.GENERIC_ENCHANT, EnchantUtils.getLocalized(enchantment)) diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/command/ListCommand.java b/Core/src/main/java/su/nightexpress/excellentenchants/command/ListCommand.java index cb1dcdb..51981bc 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/command/ListCommand.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/command/ListCommand.java @@ -3,22 +3,22 @@ package su.nightexpress.excellentenchants.command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.command.AbstractCommand; -import su.nexmedia.engine.api.command.CommandResult; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.Perms; import su.nightexpress.excellentenchants.config.Lang; +import su.nightexpress.nightcore.command.CommandResult; +import su.nightexpress.nightcore.command.impl.AbstractCommand; -public class ListCommand extends AbstractCommand { +public class ListCommand extends AbstractCommand { - public ListCommand(@NotNull ExcellentEnchants plugin) { + public ListCommand(@NotNull ExcellentEnchantsPlugin plugin) { super(plugin, new String[]{"list"}, Perms.COMMAND_LIST); - this.setDescription(plugin.getMessage(Lang.COMMAND_LIST_DESC)); + this.setDescription(Lang.COMMAND_LIST_DESC); this.setPlayerOnly(true); } @Override protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) { - plugin.getEnchantManager().getEnchantsListGUI().open((Player) sender, 1); + plugin.getEnchantManager().openEnchantsMenu((Player) sender); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/command/RarityBookCommand.java b/Core/src/main/java/su/nightexpress/excellentenchants/command/RarityBookCommand.java new file mode 100644 index 0000000..7e2267f --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/command/RarityBookCommand.java @@ -0,0 +1,91 @@ +package su.nightexpress.excellentenchants.command; + +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.Perms; +import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.config.Lang; +import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.command.CommandResult; +import su.nightexpress.nightcore.command.impl.AbstractCommand; +import su.nightexpress.nightcore.util.Lists; +import su.nightexpress.nightcore.util.Players; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.random.Rnd; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class RarityBookCommand extends AbstractCommand { + + public RarityBookCommand(@NotNull ExcellentEnchantsPlugin plugin) { + super(plugin, new String[]{"raritybook"}, Perms.COMMAND_RARITY_BOOK); + this.setDescription(Lang.COMMAND_RARITY_BOOK_DESC); + this.setUsage(Lang.COMMAND_RARITY_BOOK_USAGE); + } + + @Override + @NotNull + public List getTab(@NotNull Player player, int arg, @NotNull String[] args) { + if (arg == 1) { + return Players.playerNames(player); + } + if (arg == 2) { + return Lists.getEnums(Rarity.class); + } + if (arg == 3) { + return Arrays.asList("-1", "1", "5", "10"); + } + return super.getTab(player, arg, args); + } + + @Override + protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) { + if (result.length() < 4) { + this.errorUsage(sender); + return; + } + + Player player = Players.getPlayer(result.getArg(1)); + if (player == null) { + this.errorPlayer(sender); + return; + } + + Rarity rarity = StringUtil.getEnum(result.getArg(2), Rarity.class).orElse(null); + if (rarity == null) { + Lang.ERROR_INVALID_RARITY.getMessage().send(sender); + return; + } + + Set enchants = EnchantRegistry.getByRarity(rarity); + EnchantmentData enchantmentData = enchants.isEmpty() ? null : Rnd.get(enchants); + if (enchantmentData == null) { + Lang.ERROR_NO_ENCHANT.getMessage().send(sender); + return; + } + + int level = result.getInt(3, -1); + if (level < 1) { + level = Rnd.get(enchantmentData.getMinLevel(), enchantmentData.getMaxLevel()); + } + + ItemStack item = new ItemStack(Material.ENCHANTED_BOOK); + EnchantUtils.add(item, enchantmentData.getEnchantment(), level, true); + EnchantUtils.updateDisplay(item); + Players.addItem(player, item); + + Lang.COMMAND_RARITY_BOOK_DONE.getMessage() + .replace(Placeholders.GENERIC_NAME, plugin.getLangManager().getEnum(rarity)) + .replace(Placeholders.forPlayer(player)) + .send(sender); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/command/TierbookCommand.java b/Core/src/main/java/su/nightexpress/excellentenchants/command/TierbookCommand.java deleted file mode 100644 index f1813ac..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/command/TierbookCommand.java +++ /dev/null @@ -1,90 +0,0 @@ -package su.nightexpress.excellentenchants.command; - -import org.bukkit.Material; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.command.AbstractCommand; -import su.nexmedia.engine.api.command.CommandResult; -import su.nexmedia.engine.utils.CollectionsUtil; -import su.nexmedia.engine.utils.Placeholders; -import su.nexmedia.engine.utils.PlayerUtil; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Perms; -import su.nightexpress.excellentenchants.config.Lang; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; -import su.nightexpress.excellentenchants.tier.Tier; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -public class TierbookCommand extends AbstractCommand { - - public TierbookCommand(@NotNull ExcellentEnchants plugin) { - super(plugin, new String[]{"tierbook"}, Perms.COMMAND_TIERBOOK); - this.setDescription(plugin.getMessage(Lang.COMMAND_TIER_BOOK_DESC)); - this.setUsage(plugin.getMessage(Lang.COMMAND_TIER_BOOK_USAGE)); - } - - @Override - @NotNull - public List getTab(@NotNull Player player, int arg, @NotNull String[] args) { - if (arg == 1) { - return CollectionsUtil.playerNames(player); - } - if (arg == 2) { - return plugin.getTierManager().getTierIds(); - } - if (arg == 3) { - return Arrays.asList("-1", "1", "5", "10"); - } - return super.getTab(player, arg, args); - } - - @Override - protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) { - if (result.length() < 4) { - this.printUsage(sender); - return; - } - - Player player = PlayerUtil.getPlayer(result.getArg(1)); - if (player == null) { - this.errorPlayer(sender); - return; - } - - Tier tier = plugin.getTierManager().getTierById(result.getArg(2).toLowerCase()); - if (tier == null) { - plugin.getMessage(Lang.COMMAND_TIER_BOOK_ERROR).send(sender); - return; - } - - Set enchants = EnchantRegistry.getOfTier(tier); - ExcellentEnchant enchant = enchants.isEmpty() ? null : Rnd.get(enchants); - if (enchant == null) { - plugin.getMessage(Lang.ERROR_NO_ENCHANT).send(sender); - return; - } - - int level = result.getInt(3, -1); - if (level < 1) { - level = Rnd.get(enchant.getStartLevel(), enchant.getMaxLevel()); - } - - ItemStack item = new ItemStack(Material.ENCHANTED_BOOK); - EnchantUtils.add(item, enchant.getBackend(), level, true); - EnchantUtils.updateDisplay(item); - PlayerUtil.addItem(player, item); - - plugin.getMessage(Lang.COMMAND_TIER_BOOK_DONE) - .replace(tier.replacePlaceholders()) - .replace(Placeholders.forPlayer(player)) - .send(sender); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/config/Config.java b/Core/src/main/java/su/nightexpress/excellentenchants/config/Config.java index fa89bde..e4c897e 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/config/Config.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/config/Config.java @@ -3,166 +3,255 @@ package su.nightexpress.excellentenchants.config; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.Colors2; -import su.nexmedia.engine.utils.StringUtil; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; -import su.nightexpress.excellentenchants.tier.Tier; +import su.nightexpress.excellentenchants.api.DistributionMode; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.hook.HookId; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.wrapper.UniInt; import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; + +import static su.nightexpress.excellentenchants.Placeholders.*; +import static su.nightexpress.nightcore.util.text.tag.Tags.*; public class Config { public static final String DIR_MENU = "/menu/"; + public static final String DIR_ENCHANTS = "/enchants/"; - public static final JOption TASKS_ARROW_TRAIL_TICKS_INTERVAL = JOption.create("Tasks.Arrow_Trail.Tick_Interval", + public static final ConfigValue CORE_PROJECTILE_PARTICLE_INTERVAL = ConfigValue.create("Core.Projectile_Particles_Tick_Interval", 1L, - "Sets how often (in ticks) arrow trail particle effects will be spawned behind the arrow." + "Sets how often (in ticks) enchantment particle effects will be spawned behind projectiles.", + "[Increase for performance; Decrease for better visuals]", + "[20 ticks = 1 second]", + "[Default is 1]" ); - public static final JOption TASKS_PASSIVE_ENCHANTS_TRIGGER_INTERVAL = JOption.create("Tasks.Passive_Enchants.Trigger_Interval", + public static final ConfigValue CORE_PASSIVE_ENCHANTS_TRIGGER_INTERVAL = ConfigValue.create("Core.Passive_Enchants_Trigger_Interval", 100L, - "Sets how often (in ticks) the plugin will attempt to trigger passive enchantment effects on all alive entities.", - "For best results it's recommened to keep this value smaller, but at the same rate as enchantment 'Trigger_Interval' settings.", - "Examples:", - "--- Global: 100 ticks; Regrowth: 100 ticks; Saturation: 100 ticks;", - "--- Global: 50 ticks, Regrowth: 100 ticks; Saturation: 150 ticks;" + "Sets how often (in ticks) passive enchantment effects will trigger on all alive and loaded entities.", + "For best results it's recommened to keep this value lower, but at the same rate as enchantment's 'Trigger_Interval' option.", + "=".repeat(15) + " EXAMPLES " + "=".repeat(15), + "==> Global (this): 100 ticks; Regrowth: 200 ticks; Saturation: 300 ticks;", + "==> Global (this): 50 ticks, Regrowth: 100 ticks; Saturation: 150 ticks;", + "[Increase for performance; Decrease for more smooth effect]", + "[20 ticks = 1 second]", + "[Default is 100]" ); - public static final JOption ENCHANTMENTS_INTERNAL_HANDLER = JOption.create("Enchantments.Internal_Distributor", false, - "[EXPERIMENTAL - DO NOT TOUCH]", - "Sets whether or not enchantment distribution will be handled by vanilla server mechanics."); + public static final ConfigValue CORE_PASSIVE_ENCHANTS_FOR_MOBS = ConfigValue.create("Core.Apply_Passive_Enchants_To_Mobs", + true, + "Sets whether or not mobs can have passive enchantment effects (such as permanent potion effects, regeneration, etc.).", + "[Enable for enhanced gameplay; Disable for performance]", + "[Default is true]" + ); - public static final JOption ENCHANTMENTS_CHARGES_ENABLED = JOption.create("Enchantments.Charges.Enabled", + public static final ConfigValue CORE_SWORD_ENCHANTS_TO_AXES = ConfigValue.create("Core.Sword_Enchants_To_Axes", + true, + "Sets whether or not Sword enchantments can be applied on Axes.", + "[Default is true]" + ); + + public static final ConfigValue CORE_BOW_ENCHANTS_TO_CROSSBOW = ConfigValue.create("Core.Bow_Enchants_To_Crossbows", + true, + "Sets whether or not Bow enchantments can be applied on Crossbows.", + "[Default is true]" + ); + + public static final ConfigValue CORE_CHESTPLATE_ENCHANTS_TO_ELYTRA = ConfigValue.create("Core.Chestplate_Enchants_To_Elytra", false, - "Enables the enchantment Charges feature.", - Placeholders.URL_WIKI + "Charges-System"); + "Sets whether or not Chestplate enchantments can be applied on Elytras.", + "[Default is false]" + ); - public static final JOption> ENCHANTMENTS_CHARGES_FORMAT = new JOption>("Enchantments.Charges.Format", - (cfg, path, def) -> { - TreeMap map = new TreeMap<>(); - for (String raw : cfg.getSection(path)) { - int percent = StringUtil.getInteger(raw, -1); - if (percent < 0) continue; - String format = Colorizer.apply(cfg.getString(path + "." + raw, "")); - if (format.isEmpty()) continue; - map.put(percent, format); - } - return map; - }, + public static final ConfigValue> ENCHANTMENTS_DISABLED_LIST = ConfigValue.forSet("Enchantments.Disabled.List", + String::toLowerCase, + FileConfig::set, + Set.of("example_name", "custom_sharpness"), + "Put here CUSTOM enchantment names that you want to disable and remove completely.", + "Enchantment names are equal to their config file names in '" + DIR_ENCHANTS + "' folder.", + "[*] You MUST REBOOT your server for disabled enchantments to have effect.", + "[*] Once enchantment is disabled, it will be removed from all items in the world on next load!" + ); + + public static final ConfigValue>> ENCHANTMENTS_DISABLED_IN_WORLDS = ConfigValue.forMap("Enchantments.Disabled.ByWorld", + String::toLowerCase, + (cfg, path, worldName) -> cfg.getStringSet(path + "." + worldName).stream().map(String::toLowerCase).collect(Collectors.toSet()), + (cfg, path, map) -> map.forEach((world, enchants) -> cfg.set(path + "." + world, enchants)), + () -> Map.of( + "your_world_name", Set.of("enchantment_name", "ice_aspect"), + "another_world", Set.of("another_enchantment", "ice_aspect") + ), + "Put here CUSTOM enchantment names that you want to disable in specific worlds.", + "To disable all enchantments for a world, use '" + WILDCARD + "' instead of enchantment names.", + "Enchantment names are equal to their config file names in '" + DIR_ENCHANTS + "' folder.", + VANILLA_DISTRIBUTION_HEADER, + "Enchantments will have no effect, but will appear in the world.", + CUSTOM_DISTRIBUTION_HEADER, + "Enchantments will have no effect and won't appear in the world." + ); + + public static final ConfigValue DISTRIBUTION_MODE = ConfigValue.create("Enchantments.Distribution.Mode", + DistributionMode.class, DistributionMode.VANILLA, + "Sets in a which way new enchantments will be distributed to the worlds.", + "Allowed values: " + StringUtil.inlineEnum(DistributionMode.class, ", "), + "=".repeat(15) + " ! WARNING ! " + "=".repeat(15), + "You MUST REBOOT your server when changing this. Otherwise result is unpredictable.", + VANILLA_DISTRIBUTION_HEADER, + "[+] Very simple to use, almost no need to configure anything.", + "[+] Handled by the server, automatically supports all possible ways to get enchantments.", + "[+] Very accurate generation, repsects all vanilla game mechanics.", + "[-] Customization is almost non-existent.", + CUSTOM_DISTRIBUTION_HEADER, + "[+] Very flexible and customizable.", + "[+] Possibility for new ways to generate / obtain enchantments.", + "[-] Might be difficult to configure and balance everything.", + "[-] Enchantment generation is not such accurate as vanilla does." + ); + + public static final ConfigValue DISTRIBUTION_SINGLE_ENCHANT_IN_VILLAGER_BOOKS = ConfigValue.create("Enchantments.Distribution.Custom.Single_Enchant_In_Villager_Books", + true, + "When enabled, enchanted books in villager trades will have no more than 1 enchantment (vanilla or custom one)."); + + private static final ConfigValue> DISTRIBUTION_WAY_SETTINGS = ConfigValue.forMap("Enchantments.Distribution.Custom.Ways", + id -> StringUtil.getEnum(id, DistributionWay.class).orElse(null), + (cfg, path, def) -> DistributionWaySettings.read(cfg, path + "." + def), + (cfg, path, map) -> map.forEach((type, settings) -> settings.write(cfg, path + "." + type.name())), + () -> Map.of( + DistributionWay.ENCHANTING, new DistributionWaySettings(true, 5, 75, UniInt.of(0, 2)), + DistributionWay.FISHING, new DistributionWaySettings(true, 4, 45, UniInt.of(0, 2)), + DistributionWay.LOOT_GENERATION, new DistributionWaySettings(true, 4, 80, UniInt.of(0, 2)), + DistributionWay.MOB_EQUIPMENT, new DistributionWaySettings(true, 4, 35, UniInt.of(0, 2)), + DistributionWay.VILLAGER, new DistributionWaySettings(true, 4, 60, UniInt.of(0, 2)) + ), + "Settings for the different ways of obtaining enchantments." + ); + + + + public static final ConfigValue ENCHANTMENTS_DISPLAY_MODE = ConfigValue.create("Enchantments.Display.Mode", + 1, + "Sets how enchantment names and descriptions will be handled on items.", + "=".repeat(15) + " AVAILABLE VALUES " + "=".repeat(15), + "1 = Plain modification of item's lore (lore changes are real and persistent).", + "2 = Packet modification of item's lore (no real changes are made to the items). Requires " + HookId.PROTOCOL_LIB + " to be installed.", + "", + "Plain mode is faster, but may not reflect all changes immediately.", + "Packet mode is slower, but instantly reflect all changes. In creative mode, there is a chance for lore duplication." + ); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_NAME_HIDE_1ST_LEVEL = ConfigValue.create("Enchantments.Display.Name.Hide_1st_Level", + true, + "Hides enchantment level component from name format for level 1 enchantments."); + + public static final ConfigValue> ENCHANTMENTS_DISPLAY_NAME_RARITY_FORMAT = ConfigValue.forMap("Enchantments.Display.Name.Rarity", + (id) -> StringUtil.getEnum(id, Rarity.class).orElse(null), + (cfg, path, id) -> cfg.getString(path + "." + id, GENERIC_NAME), + (cfg, path, map) -> map.forEach((rarity, format) -> cfg.set(path + "." + rarity.name(), format)), + () -> Map.of( + Rarity.COMMON, WHITE.enclose(GENERIC_NAME), + Rarity.UNCOMMON, LIGHT_GREEN.enclose(GENERIC_NAME), + Rarity.RARE, LIGHT_CYAN.enclose(GENERIC_NAME), + Rarity.VERY_RARE, LIGHT_ORANGE.enclose(GENERIC_NAME) + ), + "Sets enchantment name format depends on enchantment rarity."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_NAME_CURSE_FORMAT = ConfigValue.create("Enchantments.Display.Name.Curse", + LIGHT_RED.enclose(GENERIC_NAME), + "Sets cursed enchantments name format."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_NAME_FORMAT = ConfigValue.create("Enchantments.Display.Name.Format", + ENCHANTMENT_NAME + ENCHANTMENT_LEVEL + ENCHANTMENT_CHARGES, + "Enchantment name format created from name components."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_NAME_COMPONENT_NAME = ConfigValue.create("Enchantments.Display.Name.Component.Name", + GENERIC_VALUE, + "Enchantment name display component for name format."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_NAME_COMPONENT_LEVEL = ConfigValue.create("Enchantments.Display.Name.Component.Level", + " " + GENERIC_VALUE, + "Enchantment level display component for name format."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_NAME_COMPONENT_CHARGES = ConfigValue.create("Enchantments.Display.Name.Component.Charges", + " " + GENERIC_VALUE, + "Enchantment charges display component for name format."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_DESCRIPTION_ENABLED = ConfigValue.create("Enchantments.Display.Description.Enabled", + true, + "When 'true', adds the enchantment description to item lore under enchantment names.", + "For Display-Mode = 2 description is not shown while you're in Creative gamemode."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_DESCRIPTION_BOOKS_ONLY = ConfigValue.create("Enchantments.Display.Description.Books_Only", + false, + "Sets whether or not only enchanted books will have enchantment descriptions."); + + public static final ConfigValue ENCHANTMENTS_DISPLAY_DESCRIPTION_FORMAT = ConfigValue.create("Enchantments.Display.Description.Format", + LIGHT_GRAY.enclose("• " + GENERIC_DESCRIPTION), + "Sets enc" + + "hantment description format."); + + + + + public static final ConfigValue ENCHANTMENTS_CHARGES_ENABLED = ConfigValue.create("Enchantments.Charges.Enabled", + false, + "Enables Enchantment Charges feature.", + "When enabled in the first time, make sure to check enchantments configs for new 'Charges' section.", + URL_CHRAGES); + + public static final ConfigValue> ENCHANTMENTS_CHARGES_FORMAT = ConfigValue.forTreeMap("Enchantments.Charges.Format", + raw -> NumberUtil.getInteger(raw, 0), + (cfg, path, value) -> cfg.getString(path + "." + value, GENERIC_AMOUNT), + (cfg, path, map) -> map.forEach((perc, str) -> cfg.set(path + "." + perc, str)), () -> { TreeMap map = new TreeMap<>(); - map.put(0, "#ff9a9a(" + Placeholders.GENERIC_AMOUNT + "⚡)"); - map.put(25, "#ffc39a(" + Placeholders.GENERIC_AMOUNT + "⚡)"); - map.put(50, "#f6ff9a(" + Placeholders.GENERIC_AMOUNT + "⚡)"); - map.put(75, "#bcff9a(" + Placeholders.GENERIC_AMOUNT + "⚡)"); + map.put(0, LIGHT_RED.enclose("(" + GENERIC_AMOUNT + "⚡)")); + map.put(25, LIGHT_ORANGE.enclose("(" + GENERIC_AMOUNT + "⚡)")); + map.put(50, LIGHT_YELLOW.enclose("(" + GENERIC_AMOUNT + "⚡)")); + map.put(75, LIGHT_GREEN.enclose("(" + GENERIC_AMOUNT + "⚡)")); return map; }, "Enchantment charges format depends on amount of charges left (in percent).", "If you don't want to display charges, leave only keys with negative values.", - "Use '" + Placeholders.GENERIC_AMOUNT + "' placeholder for amount of charges.") - .setWriter((cfg, path, map) -> map.forEach((perc, str) -> cfg.set(path + "." + perc, str))); + "Use '" + GENERIC_AMOUNT + "' placeholder for charges amount."); - public static final JOption ENCHANTMENTS_CHARGES_COMPARE_TYPE_ONLY = JOption.create("Enchantments.Charges.Compare_Material_Only", false, - "When enabled, only item material will be checked to determine if item can be used as an enchantment fuel.", - "When disabled (default), it will compare the whole item meta including name, lore, model data etc."); + public static final ConfigValue ENCHANTMENTS_CHARGES_COMPARE_TYPE_ONLY = ConfigValue.create("Enchantments.Charges.Compare_Material_Only", + false, + "When enabled, only item material will be checked to determine if an item can be used as an enchantment fuel.", + "When disabled, it will compare the whole item meta including name, lore, model data etc.", + "[Default is false]"); - public static final JOption ENCHANTMENTS_CHARGES_FUEL_ITEM = JOption.create("Enchantments.Charges.Fuel_Item", + public static final ConfigValue ENCHANTMENTS_CHARGES_FUEL_ITEM = ConfigValue.create("Enchantments.Charges.Fuel_Item", new ItemStack(Material.LAPIS_LAZULI), "Default item used to recharge item's enchantments on anvils.", "If you want different item for certain enchantments, you can do it in that enchantment configs.", - "Item Options: " + Placeholders.URL_ENGINE_SCALER) - .setWriter(JYML::setItem); - - public static final JOption> ENCHANTMENTS_DISABLED = JOption.create("Enchantments.Disabled", - Set.of("enchant_name", "other_enchant"), - "A list of enchantments, that will be disabled and removed from the game (server).", - "Enchantment names are the same as enchantment file name in /enchants/ folder. ! Must be in lower_case !", - "Example: To disable 'Explosive Arrows' you need to add 'explosive_arrows' here.") - .mapReader(set -> set.stream().map(String::toLowerCase).collect(Collectors.toSet())); - - public static final JOption>> ENCHANTMENTS_DISABLED_IN_WORLDS = new JOption>>("Enchantments.Disabled_In_Worlds", - (cfg, path, def) -> cfg.getSection(path).stream().collect(Collectors.toMap(k -> k, worldName -> cfg.getStringSet(path + "." + worldName))), - () -> Map.of("your_world_name", Set.of("enchantment_name", "ice_aspect")), - "Here you can disable certain enchantments in certain worlds.", - "Enchantment names are the same as enchantment file name in /enchants/ folder. ! Must be in lower_case !", - "To disable all enchantments for a world, use '" + Placeholders.WILDCARD + "' instead of enchantment names.") - .setWriter((cfg, path, map) -> map.forEach((world, enchants) -> cfg.set(path + "." + world, enchants))); - - public static final JOption ENCHANTMENTS_DISPLAY_MODE = JOption.create("Enchantments.Display.Mode", - 1, - "Sets how enchantment names and descriptions will be handled on items.", - "1 = Plain modification of item's lore (lore changes are real and persistent).", - "2 = Packet modification of item's lore (no real changes are made to the items). Requires ProtocolLib.", - "Plain mode is faster, but may not reflect all changes immediately.", - "Packet mode is slower, but instantly reflect all changes. In creative mode, there is a chance for lore duplication."); - - public static final JOption ENCHANTMENTS_DESCRIPTION_ENABLED = JOption.create("Enchantments.Description.Enabled", true, - "When 'true', adds the enchantment description to item lore under enchantment names.", - "For Display-Mode = 2 description is not shown while you're in Creative gamemode."); - - public static final JOption ENCHANTMENTS_DESCRIPTION_BOOKS_ONLY = JOption.create("Enchantments.Description.Books_Only", - false, - "Sets whether or not only enchanted books will have enchantment descriptions."); - - public static final JOption ENCHANTMENTS_DESCRIPTION_FORMAT = JOption.create("Enchantments.Description.Format", - "&8▸ " + Placeholders.GENERIC_DESCRIPTION, - "Sets the global enchantment description format.").mapReader(Colorizer::apply); - - public static final JOption ENCHANTMENTS_ITEM_CUSTOM_MAX = JOption.create("Enchantments.Item.Max_Custom_Enchants", 3, - "How many of custom enchantments the item can contain at the same time?"); - - public static final JOption ENCHANTMENTS_ITEM_SWORD_ENCHANTS_TO_AXES = JOption.create("Enchantments.Item.Sword_Enchants_To_Axes", true, - "Set this to 'true' to allow Sword enchantments for Axes."); - - public static final JOption ENCHANTMENTS_ITEM_BOW_ENCHANTS_TO_CROSSBOW = JOption.create("Enchantments.Item.Bow_Enchants_To_Crossbows", true, - "Set this to 'true' to allow Bow enchantments for Crossbows."); - - public static final JOption ENCHANTMENTS_ITEM_CHESTPLATE_ENCHANTS_TO_ELYTRA = JOption.create("Enchantments.Item.Chestplate_Enchants_To_Elytra", false, - "Set this to 'true' to allow Chestplate enchantments for Elytras."); - - public static final JOption ENCHANTMENTS_ENTITY_PASSIVE_FOR_MOBS = JOption.create("Enchantments.Entity.Apply_Passive_Enchants_To_Mobs", true, - "When enabled, passive enchantments (permanent potion effects, regeneration, etc.) will be applied to mobs as well.", - "Disable this if you're experiencing performance issues."); - - public static final JOption ENCHANTMENTS_SINGLE_ENCHANT_IN_VILLAGER_BOOKS = JOption.create("Enchantments.Single_Enchant_In_Villager_Books", true, - "Sets whether or not enchanted books in villager trades will have only 1 enchant, vanilla or custom one."); - - private static final JOption> OBTAIN_SETTINGS = new JOption>("Enchantments.Obtaining", - (cfg, path, def) -> Stream.of(ObtainType.values()).collect(Collectors.toMap(k -> k, v -> ObtainSettings.read(cfg, path + "." + v.getPathName()))), - () -> Stream.of(ObtainType.values()).collect(Collectors.toMap(k -> k, v -> new ObtainSettings(true, 4, 80D, 0, 2))), - "Settings for the different ways of obtaining enchantments.") - .setWriter((cfg, path, map) -> map.forEach((type, settings) -> ObtainSettings.write(cfg, path + "." + type.getPathName(), settings))); + "Item Options: " + WIKI_ITEMS_URL); @NotNull - public static Optional getObtainSettings(@NotNull ObtainType obtainType) { - ObtainSettings settings = OBTAIN_SETTINGS.get().get(obtainType); + public static Optional getDistributionWaySettings(@NotNull DistributionWay way) { + DistributionWaySettings settings = DISTRIBUTION_WAY_SETTINGS.get().get(way); return settings == null || !settings.isEnabled() ? Optional.empty() : Optional.of(settings); } - @NotNull - public static List getDefaultTiers() { - List list = new ArrayList<>(); - list.add(new Tier("common", 1, "Common", Colors2.WHITE, getObtainWeight(50D))); - list.add(new Tier("rare", 2, "Rare", Colors2.GREEN, getObtainWeight(25D))); - list.add(new Tier("unique", 3, "Unique", Colors2.YELLOW, getObtainWeight(15D))); - list.add(new Tier("legendary", 4, "Legendary", Colors2.ORANGE, getObtainWeight(5D))); - return list; + public static void loadRarityWeights(@NotNull FileConfig config) { + for (Rarity rarity : Rarity.values()) { + int weight = ConfigValue.create("Enchantments.Distribution.Custom.Rarity_Weights." + rarity.name(), rarity.getWeight()).read(config); + rarity.setWeight(weight); + } } - @NotNull - private static Map getObtainWeight(double weight) { - Map map = new HashMap<>(); - for (ObtainType obtainType : ObtainType.values()) { - map.put(obtainType, weight); - } - return map; + public static boolean isVanillaDistribution() { + return Config.DISTRIBUTION_MODE.get() == DistributionMode.VANILLA; + } + + public static boolean isCustomDistribution() { + return Config.DISTRIBUTION_MODE.get() == DistributionMode.CUSTOM; } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/config/DistributionWaySettings.java b/Core/src/main/java/su/nightexpress/excellentenchants/config/DistributionWaySettings.java new file mode 100644 index 0000000..257604c --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/config/DistributionWaySettings.java @@ -0,0 +1,60 @@ +package su.nightexpress.excellentenchants.config; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniInt; + +public class DistributionWaySettings { + + private final boolean enabled; + private final int maxEnchantments; + private final double generationChance; + private final UniInt amount; + + public DistributionWaySettings(boolean enabled, + int maxEnchantments, double generationChance, + @NotNull UniInt amount) { + this.enabled = enabled; + this.maxEnchantments = maxEnchantments; + this.generationChance = generationChance; + this.amount = amount; + } + + @NotNull + public static DistributionWaySettings read(@NotNull FileConfig cfg, @NotNull String path) { + boolean enabled = cfg.getBoolean(path + ".Enabled"); + int maxEnchantments = cfg.getInt(path + ".Max_Enchantments", 4); + double generationChance = cfg.getDouble(path + ".Generation_Chance", 50D); + UniInt amount = UniInt.read(cfg, path + ".Amount"); + + return new DistributionWaySettings(enabled, maxEnchantments, generationChance, amount); + } + + public void write(@NotNull FileConfig cfg, @NotNull String path) { + cfg.set(path + ".Enabled", this.isEnabled()); + cfg.set(path + ".Max_Enchantments", this.getMaxEnchantments()); + cfg.set(path + ".Generation_Chance", this.getGenerationChance()); + this.amount.write(cfg, path + ".Amount"); + } + + public int rollAmount() { + return this.amount.roll(); + } + + public boolean isEnabled() { + return enabled; + } + + public int getMaxEnchantments() { + return maxEnchantments; + } + + public double getGenerationChance() { + return generationChance; + } + + @NotNull + public UniInt getAmount() { + return amount; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/config/Keys.java b/Core/src/main/java/su/nightexpress/excellentenchants/config/Keys.java new file mode 100644 index 0000000..26c6f2a --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/config/Keys.java @@ -0,0 +1,20 @@ +package su.nightexpress.excellentenchants.config; + +import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; + +public class Keys { + + public static NamespacedKey loreSize; + + public static NamespacedKey itemRecharged; + + public static NamespacedKey entitySpawnReason; + + public static void loadKeys(@NotNull ExcellentEnchantsPlugin plugin) { + loreSize = new NamespacedKey(plugin, "lore_size"); + itemRecharged = new NamespacedKey(plugin, "item.recharged"); + entitySpawnReason = new NamespacedKey(plugin, "entity.spawn_reason"); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/config/Lang.java b/Core/src/main/java/su/nightexpress/excellentenchants/config/Lang.java index 1baeeba..68437ef 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/config/Lang.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/config/Lang.java @@ -1,30 +1,54 @@ package su.nightexpress.excellentenchants.config; -import su.nexmedia.engine.api.lang.LangKey; -import su.nexmedia.engine.lang.EngineLang; +import su.nightexpress.nightcore.core.CoreLang; +import su.nightexpress.nightcore.language.entry.LangString; +import su.nightexpress.nightcore.language.entry.LangText; -import static su.nexmedia.engine.utils.Colors2.*; import static su.nightexpress.excellentenchants.Placeholders.*; +import static su.nightexpress.nightcore.util.text.tag.Tags.*; -public class Lang extends EngineLang { +public class Lang extends CoreLang { - public static final LangKey COMMAND_LIST_DESC = LangKey.of("Command.List.Desc", "List of all custom enchantments."); + public static final LangString COMMAND_LIST_DESC = LangString.of("Command.List.Desc", + "List of all custom enchantments."); - public static final LangKey COMMAND_ENCHANT_USAGE = LangKey.of("Command.Enchant.Usage", " [player] [slot]"); - public static final LangKey COMMAND_ENCHANT_DESC = LangKey.of("Command.Enchant.Desc", "Enchants the item in your hand."); - public static final LangKey COMMAND_ENCHANT_DONE_SELF = LangKey.of("Command.Enchant.Done.Self", LIGHT_ORANGE + GENERIC_ITEM + LIGHT_YELLOW + " enchanted with " + GENERIC_ENCHANT + " " + GENERIC_LEVEL + LIGHT_YELLOW + "!"); - public static final LangKey COMMAND_ENCHANT_DONE_OTHERS = LangKey.of("Command.Enchant.Done.Others", LIGHT_ORANGE + PLAYER_DISPLAY_NAME + LIGHT_YELLOW + "'s " + LIGHT_ORANGE + GENERIC_ITEM + LIGHT_YELLOW + " enchanted with " + GENERIC_ENCHANT + " " + GENERIC_LEVEL + LIGHT_YELLOW + "!"); - public static final LangKey COMMAND_ENCHANT_ERROR_NO_ITEM = LangKey.of("Command.Enchant.Error.NoItem", RED + "There is no item to enchant!"); + public static final LangString COMMAND_ENCHANT_USAGE = LangString.of("Command.Enchant.Usage", + " [player] [slot]"); - public static final LangKey COMMAND_BOOK_USAGE = LangKey.of("Command.Book.Usage", " "); - public static final LangKey COMMAND_BOOK_DESC = LangKey.of("Command.Book.Desc", "Gives custom enchanted book."); - public static final LangKey COMMAND_BOOK_DONE = LangKey.of("Command.Book.Done", LIGHT_YELLOW + "Given " + LIGHT_ORANGE + GENERIC_ENCHANT + LIGHT_YELLOW + " enchanted book to " + LIGHT_ORANGE + PLAYER_DISPLAY_NAME + LIGHT_YELLOW + "."); + public static final LangString COMMAND_ENCHANT_DESC = LangString.of("Command.Enchant.Desc", + "Enchants the item in your hand."); - public static final LangKey COMMAND_TIER_BOOK_USAGE = LangKey.of("Command.TierBook.Usage", " "); - public static final LangKey COMMAND_TIER_BOOK_DESC = LangKey.of("Command.TierBook.Desc", "Gives an enchanted book."); - public static final LangKey COMMAND_TIER_BOOK_ERROR = LangKey.of("Command.TierBook.Error", RED + "Invalid tier!"); - public static final LangKey COMMAND_TIER_BOOK_DONE = LangKey.of("Command.TierBook.Done", LIGHT_YELLOW + "Given " + LIGHT_ORANGE + TIER_NAME + LIGHT_YELLOW + " enchanted book to " + LIGHT_ORANGE + PLAYER_DISPLAY_NAME + LIGHT_YELLOW + "."); + public static final LangText COMMAND_ENCHANT_DONE_SELF = LangText.of("Command.Enchant.Done.Self", + LIGHT_GRAY.enclose(LIGHT_YELLOW.enclose(GENERIC_ITEM) + " enchanted with " + LIGHT_YELLOW.enclose(GENERIC_ENCHANT + " " + GENERIC_LEVEL) + "!")); - public static final LangKey ERROR_NO_ENCHANT = LangKey.of("Error.NoEnchant", RED + "Invalid enchantment."); + public static final LangText COMMAND_ENCHANT_DONE_OTHERS = LangText.of("Command.Enchant.Done.Others", + LIGHT_GRAY.enclose(LIGHT_YELLOW.enclose(PLAYER_DISPLAY_NAME) + "'s " + LIGHT_YELLOW.enclose(GENERIC_ITEM) + " enchanted with " + LIGHT_YELLOW.enclose(GENERIC_ENCHANT + " " + GENERIC_LEVEL) + "!")); + + public static final LangText COMMAND_ENCHANT_ERROR_NO_ITEM = LangText.of("Command.Enchant.Error.NoItem", + RED.enclose("There is no item to enchant!")); + + public static final LangString COMMAND_BOOK_USAGE = LangString.of("Command.Book.Usage", + " "); + + public static final LangString COMMAND_BOOK_DESC = LangString.of("Command.Book.Desc", + "Gives custom enchanted book."); + + public static final LangText COMMAND_BOOK_DONE = LangText.of("Command.Book.Done", + LIGHT_GRAY.enclose("Given " + LIGHT_YELLOW.enclose(GENERIC_ENCHANT) + " enchanted book to " + LIGHT_YELLOW.enclose(PLAYER_DISPLAY_NAME) + ".")); + + public static final LangString COMMAND_RARITY_BOOK_USAGE = LangString.of("Command.RarityBook.Usage", + " "); + + public static final LangString COMMAND_RARITY_BOOK_DESC = LangString.of("Command.RarityBook.Desc", + "Give an enchanted book with enchantment of specified rarity."); + + public static final LangText COMMAND_RARITY_BOOK_DONE = LangText.of("Command.RarityBook.Done", + LIGHT_GRAY.enclose("Given " + LIGHT_YELLOW.enclose(GENERIC_NAME) + " enchanted book to " + LIGHT_YELLOW.enclose(PLAYER_DISPLAY_NAME) + ".")); + + public static final LangText ERROR_NO_ENCHANT = LangText.of("Error.NoEnchant", + RED.enclose("Invalid enchantment.")); + + public static final LangText ERROR_INVALID_RARITY = LangText.of("Error.InvalidRarity", + RED.enclose("Invalid rarity!")); } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/config/ObtainSettings.java b/Core/src/main/java/su/nightexpress/excellentenchants/config/ObtainSettings.java deleted file mode 100644 index d4d737f..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/config/ObtainSettings.java +++ /dev/null @@ -1,67 +0,0 @@ -package su.nightexpress.excellentenchants.config; - -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JYML; - -public class ObtainSettings { - - private final boolean isEnabled; - private final int enchantsTotalMax; - private final double enchantsCustomGenerationChance; - private final int enchantsCustomMin; - private final int enchantsCustomMax; - - public ObtainSettings(boolean isEnabled, - int enchantsTotalMax, double enchantsCustomGenerationChance, - int enchantsCustomMin, int enchantsCustomMax) { - this.isEnabled = isEnabled; - this.enchantsTotalMax = enchantsTotalMax; - this.enchantsCustomGenerationChance = enchantsCustomGenerationChance; - this.enchantsCustomMin = enchantsCustomMin; - this.enchantsCustomMax = enchantsCustomMax; - } - - @NotNull - public static ObtainSettings read(@NotNull JYML cfg, @NotNull String path) { - boolean isEnabled = cfg.getBoolean(path + ".Enabled"); - int enchantsTotalMax = cfg.getInt(path + ".Enchantments.Total_Maximum", 4); - double enchantsCustomGenerationChance = cfg.getDouble(path + ".Enchantments.Custom_Generation_Chance", 50D); - int enchantsCustomMin = cfg.getInt(path + ".Enchantments.Custom_Minimum", 0); - int enchantsCustomMax = cfg.getInt(path + ".Enchantments.Custom_Maximum", 2); - - return new ObtainSettings(isEnabled, enchantsTotalMax, enchantsCustomGenerationChance, enchantsCustomMin, enchantsCustomMax); - } - - public static void write(@NotNull JYML cfg, @NotNull String path, @NotNull ObtainSettings settings) { - cfg.set(path + ".Enabled", settings.isEnabled()); - cfg.set(path + ".Enchantments.Total_Maximum", settings.getEnchantsTotalMax()); - cfg.set(path + ".Enchantments.Custom_Generation_Chance", settings.getEnchantsCustomGenerationChance()); - cfg.set(path + ".Enchantments.Custom_Minimum", settings.getEnchantsCustomMin()); - cfg.set(path + ".Enchantments.Custom_Maximum", settings.getEnchantsCustomMax()); - } - - public boolean isEnabled() { - return isEnabled; - } - - public int getEnchantsTotalMax() { - return enchantsTotalMax; - } - - public double getEnchantsCustomGenerationChance() { - return enchantsCustomGenerationChance; - } - - public int getEnchantsCustomMin() { - return enchantsCustomMin; - } - - public int getEnchantsCustomMax() { - return enchantsCustomMax; - } - - @Override - public String toString() { - return "ObtainSettings{" + "enchantsTotalMax=" + enchantsTotalMax + ", enchantsCustomGenerationChance=" + enchantsCustomGenerationChance + ", enchantsCustomMin=" + enchantsCustomMin + ", enchantsCustomMax=" + enchantsCustomMax + '}'; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantManager.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantManager.java index c1e7ca0..125bc89 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantManager.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantManager.java @@ -1,63 +1,123 @@ -/* - * Decompiled with CFR 0.151. - * - * Could not load the following classes: - * org.jetbrains.annotations.NotNull - * su.nexmedia.engine.NexPlugin - * su.nexmedia.engine.api.manager.AbstractManager - * su.nexmedia.engine.api.manager.EventListener - */ package su.nightexpress.excellentenchants.enchantment; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.AbstractManager; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; +import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.enchantment.impl.armor.FlameWalkerEnchant; import su.nightexpress.excellentenchants.enchantment.listener.EnchantAnvilListener; import su.nightexpress.excellentenchants.enchantment.listener.EnchantGenericListener; +import su.nightexpress.excellentenchants.enchantment.listener.EnchantPopulationListener; import su.nightexpress.excellentenchants.enchantment.menu.EnchantmentsListMenu; -import su.nightexpress.excellentenchants.enchantment.task.ArrowTrailsTask; -import su.nightexpress.excellentenchants.enchantment.task.PassiveEnchantsTask; +import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.manager.AbstractManager; +import su.nightexpress.nightcore.util.Pair; -public class EnchantManager -extends AbstractManager { +import java.util.*; + +public class EnchantManager extends AbstractManager { + + private final Set> passiveEnchants; - public static final String DIR_ENCHANTS = "/enchants/"; private EnchantmentsListMenu enchantmentsListMenu; - private ArrowTrailsTask arrowTrailsTask; - private PassiveEnchantsTask passiveEnchantsTask; - public EnchantManager(@NotNull ExcellentEnchants plugin) { + public EnchantManager(@NotNull ExcellentEnchantsPlugin plugin) { super(plugin); + this.passiveEnchants = new HashSet<>(); + + EnchantRegistry.getEnchantments(PassiveEnchant.class).forEach(passiveEnchant -> { + EnchantmentData enchantmentData = EnchantRegistry.getById(passiveEnchant.getId()); + if (enchantmentData == null) return; + + this.passiveEnchants.add(Pair.of(passiveEnchant, enchantmentData)); + }); } protected void onLoad() { this.enchantmentsListMenu = new EnchantmentsListMenu(this.plugin); - this.addListener(new EnchantGenericListener(this)); + + this.addListener(new EnchantGenericListener(this.plugin, this)); this.addListener(new EnchantAnvilListener(this.plugin)); - this.arrowTrailsTask = new ArrowTrailsTask(this.plugin); - this.arrowTrailsTask.start(); - this.passiveEnchantsTask = new PassiveEnchantsTask(this.plugin); - this.passiveEnchantsTask.start(); + + if (Config.isCustomDistribution()) { + this.plugin.info("Using custom distribution system..."); + this.addListener(new EnchantPopulationListener(this.plugin)); + } + + this.addTask(this.plugin.createAsyncTask(this::displayProjectileTrails).setTicksInterval(Config.CORE_PROJECTILE_PARTICLE_INTERVAL.get())); + this.addTask(this.plugin.createTask(this::updatePassiveEnchantEffects).setTicksInterval(Config.CORE_PASSIVE_ENCHANTS_TRIGGER_INTERVAL.get())); + if (EnchantRegistry.isRegistered(FlameWalkerEnchant.ID)) { + this.addTask(this.plugin.createTask(FlameWalkerEnchant::tickBlocks).setSecondsInterval(1)); + } } protected void onShutdown() { - if (this.enchantmentsListMenu != null) { - this.enchantmentsListMenu.clear(); - this.enchantmentsListMenu = null; - } - if (this.arrowTrailsTask != null) { - this.arrowTrailsTask.stop(); - this.arrowTrailsTask = null; - } - if (this.passiveEnchantsTask != null) { - this.passiveEnchantsTask.stop(); - this.passiveEnchantsTask = null; + if (this.enchantmentsListMenu != null) this.enchantmentsListMenu.clear(); + + if (EnchantRegistry.isRegistered(FlameWalkerEnchant.ID)) { + FlameWalkerEnchant.clear(); } } @NotNull - public EnchantmentsListMenu getEnchantsListGUI() { - return this.enchantmentsListMenu; + public EnchantmentsListMenu getEnchantmentsListMenu() { + return enchantmentsListMenu; + } + + public void openEnchantsMenu(@NotNull Player player) { + this.enchantmentsListMenu.open(player); + } + + private void displayProjectileTrails() { + EnchantUtils.getEnchantedProjectiles().removeIf(enchantedProjectile -> { + if (!enchantedProjectile.isValid()) { + return true; + } + + enchantedProjectile.playParticles(); + return false; + }); + } + + private void updatePassiveEnchantEffects() { + if (this.passiveEnchants.isEmpty()) return; + + Set entities = this.getPassiveEnchantEntities(); + + this.passiveEnchants.forEach(pair -> { + PassiveEnchant enchant = pair.getFirst(); + EnchantmentData enchantmentData = pair.getSecond(); + if (!enchant.isTriggerTime()) return; + + for (LivingEntity entity : entities) { + EnchantUtils.getEquipped(entity, enchantmentData).forEach((item, level) -> { + if (!enchant.isAvailableToUse(entity)) return; + if (enchant.isOutOfCharges(item)) return; + if (enchant.onTrigger(entity, item, level)) { + enchant.consumeCharges(item, level); + } + }); + } + + enchant.updateTriggerTime(); + }); + } + + @NotNull + private Set getPassiveEnchantEntities() { + Set list = new HashSet<>(plugin.getServer().getOnlinePlayers()); + + if (Config.CORE_PASSIVE_ENCHANTS_FOR_MOBS.get()) { + plugin.getServer().getWorlds().stream().filter(world -> !world.getPlayers().isEmpty()).forEach(world -> { + list.addAll(world.getEntitiesByClass(LivingEntity.class)); + }); + } + list.removeIf(entity -> entity.isDead() || !entity.isValid()); + return list; } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantPopulator.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantPopulator.java index 07c4653..d82a1b6 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantPopulator.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/EnchantPopulator.java @@ -6,44 +6,47 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.config.ObtainSettings; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.config.DistributionWaySettings; +import su.nightexpress.excellentenchants.enchantment.data.CustomDistribution; import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; -import su.nightexpress.excellentenchants.tier.Tier; +import su.nightexpress.nightcore.util.random.Rnd; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; -import java.util.stream.Collectors; +import java.util.function.BiFunction; public class EnchantPopulator { - private final ExcellentEnchants plugin; - private final ObtainType obtainType; - private final ItemStack item; - private final Map> candidates; - private final Map population; + //private final ExcellentEnchants plugin; + + private final DistributionWay distributionWay; + private final ItemStack item; + private final Map> candidates; + private final Map defaultPopulation; + private final Set> predicates; private World world; - private Function levelGenerator; + private BiFunction levelGenerator; - public EnchantPopulator(@NotNull ExcellentEnchants plugin, @NotNull ItemStack item, @NotNull ObtainType obtainType) { - this.plugin = plugin; + public EnchantPopulator(@NotNull ExcellentEnchantsPlugin plugin, @NotNull ItemStack item, @NotNull DistributionWay distributionWay) { + //this.plugin = plugin; this.item = item; - this.obtainType = obtainType; + this.distributionWay = distributionWay; this.candidates = new HashMap<>(); - this.population = new HashMap<>(); - this.withLevelGenerator(enchant -> enchant.generateLevel(this.getObtainType())); + this.defaultPopulation = new HashMap<>(); + this.predicates = new HashSet<>(); + this.withLevelGenerator((data, distribution) -> distribution.generateLevel(this.getDistributionWay())); - this.fillDefaultCandidates(); + //this.fillDefaultCandidates(); } @NotNull @@ -53,42 +56,61 @@ public class EnchantPopulator { } @NotNull - public EnchantPopulator withLevelGenerator(@NotNull Function levelGenerator) { + public EnchantPopulator withLevelGenerator(@NotNull BiFunction levelGenerator) { this.levelGenerator = levelGenerator; return this; } + @NotNull + public EnchantPopulator withCondition(@NotNull BiFunction predicate) { + this.predicates.add(predicate); + return this; + } + @NotNull public EnchantPopulator withDefaultPopulation(@NotNull Map population) { - this.getPopulation().putAll(population); + this.defaultPopulation.putAll(population); + //this.getPopulation().putAll(population); return this; } private void fillDefaultCandidates() { - this.plugin.getTierManager().getTiers().forEach(tier -> { - Set enchants = EnchantRegistry.getOfTier(tier); + for (Rarity rarity : Rarity.values()) { + Set dataSet = EnchantRegistry.getEnchantments(rarity); - enchants.removeIf(enchant -> { - return !enchant.isObtainable(this.getObtainType()) || (!enchant.getBackend().canEnchantItem(this.getItem()) && !EnchantUtils.isBook(this.getItem())); + dataSet.removeIf(data -> { + CustomDistribution distribution = (CustomDistribution) data.getDistributionOptions(); + + // Check if can be distributed. + if (!distribution.isDistributable(this.getDistributionWay())) return true; + + // Check for custom conditions. + if (!this.predicates.isEmpty() && !this.predicates.stream().allMatch(predicate -> predicate.apply(data, distribution))) return true; + + // Enchanting books is always good. + if (this.getItem().getType() == Material.BOOK && this.getDistributionWay() == DistributionWay.ENCHANTING) return false; + + // Check if item can be enchanted. + return !data.getEnchantment().canEnchantItem(this.getItem()) && !EnchantUtils.isEnchantedBook(this.getItem()); }); - this.candidates.put(tier, enchants); - }); + this.candidates.put(rarity, dataSet); + } } public boolean isEmpty() { return this.getCandidates().isEmpty() || this.getCandidates().values().stream().allMatch(Set::isEmpty); } - public boolean isEmpty(@NotNull Tier tier) { - return this.getCandidates(tier).isEmpty(); + public boolean isEmpty(@NotNull Rarity rarity) { + return this.getCandidates(rarity).isEmpty(); } - public void purge(@NotNull Tier tier) { - this.getCandidates().remove(tier); + public void purge(@NotNull Rarity rarity) { + this.getCandidates().remove(rarity); } - public void purge(@NotNull Tier tier, @NotNull ExcellentEnchant enchant) { + public void purge(@NotNull Rarity tier, @NotNull EnchantmentData enchant) { this.getCandidates(tier).remove(enchant); this.getCandidates().keySet().removeIf(this::isEmpty); } @@ -99,8 +121,8 @@ public class EnchantPopulator { } @NotNull - public ObtainType getObtainType() { - return obtainType; + public DistributionWay getDistributionWay() { + return distributionWay; } @Nullable @@ -109,89 +131,98 @@ public class EnchantPopulator { } @NotNull - public Function getLevelGenerator() { + public BiFunction getLevelGenerator() { return levelGenerator; } @NotNull - public Map> getCandidates() { + public Map> getCandidates() { return this.candidates; } @NotNull - public Set getCandidates(@NotNull Tier tier) { - return this.getCandidates().getOrDefault(tier, new HashSet<>()); - } - - @NotNull - public Map getPopulation() { - return this.population; + public Set getCandidates(@NotNull Rarity rarity) { + return this.candidates.getOrDefault(rarity, new HashSet<>()); } @Nullable - public Tier getTierByChance() { - Map map = this.getCandidates().keySet().stream() - .filter(tier -> tier.getChance(this.getObtainType()) > 0D) - .collect(Collectors.toMap(k -> k, v -> v.getChance(this.getObtainType()), (o, n) -> n, HashMap::new)); - if (map.isEmpty()) return null; + public Rarity getRarityByWeight() { + Map map = new HashMap<>(); - return Rnd.getByWeight(map); + for (Rarity rarity : this.getCandidates().keySet()) { + map.put(rarity, (double) rarity.getWeight()); + } + + return map.isEmpty() ? null : Rnd.getByWeight(map); } @Nullable - public ExcellentEnchant getEnchantByChance(@NotNull Tier tier) { - Map map = this.getCandidates(tier).stream() - .collect(Collectors.toMap(k -> k, v -> v.getObtainChance(this.getObtainType()))); + public EnchantmentData getEnchantmentByWeight(@NotNull Rarity rarity) { + Map map = new HashMap<>(); + + this.getCandidates(rarity).forEach(enchantmentData -> { + CustomDistribution distribution = (CustomDistribution) enchantmentData.getDistributionOptions(); + map.put(enchantmentData, distribution.getWeight(this.getDistributionWay())); + }); + return map.isEmpty() ? null : Rnd.getByWeight(map); } @NotNull public Map createPopulation() { - Map population = this.getPopulation(); + this.candidates.clear(); + this.fillDefaultCandidates(); - ObtainSettings settings = Config.getObtainSettings(this.getObtainType()).orElse(null); - if (settings == null || !Rnd.chance(settings.getEnchantsCustomGenerationChance())) return population; + Map population = new HashMap<>(this.defaultPopulation); - int enchantsLimit = settings.getEnchantsTotalMax(); - int enchantsRolled = Rnd.get(settings.getEnchantsCustomMin(), settings.getEnchantsCustomMax()); + DistributionWaySettings settings = Config.getDistributionWaySettings(this.getDistributionWay()).orElse(null); + if (settings == null || !Rnd.chance(settings.getGenerationChance())) return population; + + int enchantsLimit = settings.getMaxEnchantments(); + int enchantsRolled = settings.rollAmount(); // Try to populate as many as possible. while (!this.isEmpty() && enchantsRolled > 0) { // Limit reached. if (population.size() >= enchantsLimit) break; - Tier tier = this.getTierByChance(); - if (tier == null) break; // no tiers left. + Rarity rarity = this.getRarityByWeight(); + if (rarity == null) break; // no tiers left. - ExcellentEnchant enchant = this.getEnchantByChance(tier); - // Remove entire tier if no enchants can be selected. - if (enchant == null) { - this.purge(tier); + EnchantmentData enchantmentData = this.getEnchantmentByWeight(rarity); + // Remove entire rarity if no enchants can be selected. + if (enchantmentData == null) { + this.purge(rarity); + continue; + } + + if (!(enchantmentData.getDistributionOptions() instanceof CustomDistribution distribution)) { + this.purge(rarity, enchantmentData); continue; } // Remove disabled world enchants. - if (world != null && enchant.isDisabledInWorld(world)) { - this.purge(tier, enchant); + if (this.world != null && !enchantmentData.isAvailableToUse(this.world)) { + this.purge(rarity, enchantmentData); continue; } // Remove conflicting enchants. - if (population.keySet().stream().anyMatch(has -> has.conflictsWith(enchant.getBackend()) || enchant.getBackend().conflictsWith(has))) { - this.purge(tier, enchant); + if (population.keySet().stream().anyMatch(has -> has.conflictsWith(enchantmentData.getEnchantment()) || enchantmentData.getEnchantment().conflictsWith(has))) { + this.purge(rarity, enchantmentData); continue; } // Level generation failed. - int level = this.getLevelGenerator().apply(enchant); - if (level < enchant.getStartLevel()) { - this.purge(tier, enchant); + int level = this.getLevelGenerator().apply(enchantmentData, distribution); + if (level < enchantmentData.getMinLevel()) { + this.purge(rarity, enchantmentData); continue; } // All good! - this.purge(tier, enchant); - population.put(enchant.getBackend(), level); + this.purge(rarity, enchantmentData); + population.put(enchantmentData.getEnchantment(), level); enchantsRolled--; } @@ -201,16 +232,15 @@ public class EnchantPopulator { public boolean populate() { ItemStack item = this.getItem(); AtomicBoolean status = new AtomicBoolean(false); + Map population = this.createPopulation();//this.getPopulation().isEmpty() ? this.createPopulation() : this.getPopulation(); - var population = this.getPopulation().isEmpty() ? this.createPopulation() : this.getPopulation(); - - boolean singleVillagerBook = this.getObtainType() == ObtainType.VILLAGER - && item.getType() == Material.ENCHANTED_BOOK - && Config.ENCHANTMENTS_SINGLE_ENCHANT_IN_VILLAGER_BOOKS.get(); + boolean singleVillagerBook = this.getDistributionWay() == DistributionWay.VILLAGER + && EnchantUtils.isEnchantedBook(item) + && Config.DISTRIBUTION_SINGLE_ENCHANT_IN_VILLAGER_BOOKS.get(); if (singleVillagerBook) { if (!population.isEmpty()) { - EnchantUtils.getAll(item).keySet().forEach(enchantment -> EnchantUtils.remove(item, enchantment)); + EnchantUtils.removeAll(item); } while (population.size() > 1) { population.remove(Rnd.get(population.keySet())); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/config/EnchantDefaults.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/config/EnchantDefaults.java deleted file mode 100644 index ba53052..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/config/EnchantDefaults.java +++ /dev/null @@ -1,361 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.config; - -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.StringUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.ExcellentEnchantsAPI; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; -import su.nightexpress.excellentenchants.tier.Tier; -import su.nightexpress.excellentenchants.tier.TierManager; - -import java.util.*; - -public class EnchantDefaults { - - private final Map obtainChance; - private final Map obtainLevelCap; - - private String displayName; - private Tier tier; - private List description; - private boolean hiddenFromList; - private boolean isTreasure; - private boolean tradeable; - private boolean discoverable; - private int levelMin; - private int levelMax; - private int maxMergeLevel; - private EnchantScaler levelByEnchantCost; - private EnchantScaler anvilMergeCost; - private Set conflicts; - private boolean visualEffects; - - private boolean chargesEnabled; - private boolean chargesCustomFuel; - private EnchantScaler chargesMax; - private EnchantScaler chargesConsumeAmount; - private EnchantScaler chargesRechargeAmount; - private ItemStack chargesFuel; - - public EnchantDefaults(@NotNull ExcellentEnchant enchant) { - this.setDisplayName(StringUtil.capitalizeUnderscored(enchant.getId())); - this.setTier(0.1); - this.setDescription(new ArrayList<>()); - this.setHiddenFromList(false); - this.setTreasure(false); - this.setTradeable(true); - this.setDiscoverable(true); - this.setLevelMin(1); - this.setLevelMax(3); - this.setMaxMergeLevel(-1); - this.setConflicts(new HashSet<>()); - this.setVisualEffects(true); - this.obtainChance = new HashMap<>(); - this.obtainLevelCap = new HashMap<>(); - } - - public void load(@NotNull ExcellentEnchant enchant) { - ExcellentEnchants plugin = ExcellentEnchantsAPI.PLUGIN; - JYML cfg = enchant.getConfig(); - - this.setDisplayName(JOption.create("Name", this.getDisplayName(), - "Enchantment display name. It will be shown in item lore.").read(cfg)); - - Tier tier = plugin.getTierManager().getTierById(JOption.create("Tier", this.getTier().getId(), - "Enchantment tier. Must be a valid tier identifier from the '" + TierManager.FILE_NAME + "'.").read(cfg)); - this.setTier(tier == null ? plugin.getTierManager().getMostCommon() : tier); - //this.getTier().getEnchants().add(enchant); - - this.setDescription(JOption.create("Description", this.getDescription(), - "Enchantment description. It will be shown in item lore under enchantment name.", - "You can use 'Enchantment' placeholders: " + Placeholders.URL_PLACEHOLDERS) - .read(cfg)); - - this.setHiddenFromList(JOption.create("Hide_From_List", false, - "Sets whether or not this enchantment will be hidden from Enchants GUI.").read(cfg)); - - this.setTreasure(JOption.create("Is_Treasure", this.isTreasure(), - "Sets whether this enchantment is a treasure enchantment.", - "Treasure enchantments can only be received via looting, trading, or fishing.").read(cfg)); - - if (Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) { - this.setTradeable(JOption.create("Tradeable", this.isTradeable(), - "Sets whether or not this enchantment can be populated in villager trades.").read(cfg)); - - this.setDiscoverable(JOption.create("Discoverable", this.isTradeable(), - "Sets whether or not this enchantment can be populated in enchanting table.").read(cfg)); - } - else { - this.setTradeable(false); - this.setDiscoverable(false); - } - - this.setLevelMin(JOption.create("Level.Min", this.getLevelMin(), - "Sets the minimal (start) enchantment level. Can not be less than 1.").read(cfg)); - - this.setLevelMax(JOption.create("Level.Max", this.getLevelMax(), - "Sets the maximal enchantment level. Can not be less than min. level.", - "Note: While you can 'bypass' this value by enchant commands, all level-dependant enchantment", - "settings will have a limit up to this setting.").read(cfg)); - - this.setMaxMergeLevel(JOption.create("Anvil.Max_Merge_Level", this.getMaxMergeLevel(), - "Sets max. enchantment level that can be obtained by combining 2 items with this enchantment.", - "Set this to '-1' to remove merge limit and just use 'Max Level' instead." - ).read(cfg)); - - this.setLevelByEnchantCost(EnchantScaler.read(enchant, ObtainType.ENCHANTING.getPathName() + ".Level_By_Exp_Cost", - (int)(30D / this.levelMax) + " * " + Placeholders.ENCHANTMENT_LEVEL, - "Sets how much XP levels must be used in enchanting table to obtain this enchantment.", - "With a default formula '9 * %enchantment_level%' it will be [9, 18, 27] XP levels for [1, 2, 3] enchantment levels.")); - - this.setAnvilMergeCost(EnchantScaler.read(enchant, "Anvil.Merge_Cost", Placeholders.ENCHANTMENT_LEVEL, - "Sets how much XP levels will be added to the anvil cost when combining custom enchantments.")); - - for (ObtainType obtainType : ObtainType.values()) { - double obtainChance = JOption.create(obtainType.getPathName() + ".Chance", 50D, - "Chance for this enchantment to be obtained via " + obtainType.getPathName()).read(cfg); - this.getObtainChance().put(obtainType, obtainChance); - - int levelMin = JOption.create(obtainType.getPathName() + ".Level.Min", -1, - "Minimal level when obtained via " + obtainType.getPathName(), - "Can not be less than enchantment min. level. Set -1 to use enchantment min. level.").read(cfg); - int levelMax = JOption.create(obtainType.getPathName() + ".Level.Max", -1, - "Maximal level when obtained via " + obtainType.getPathName(), - "Can not be greater than enchantment max. level. Set -1 to use enchantment max. level.").read(cfg); - this.getObtainLevelCap().put(obtainType, new int[]{levelMin, levelMax}); - } - - - this.setConflicts(JOption.create("Conflicts", this.getConflicts(), - "A list of conflicting enchantment names.", - "Conflicting enchantments can not be combined on anvils and obtained together on the same item.").read(cfg)); - - this.setVisualEffects(JOption.create("Settings.Visual_Effects", this.isVisualEffects(), - "Enables/Disables enchantment visual effects, such as particles.").read(cfg)); - - - if (Config.ENCHANTMENTS_CHARGES_ENABLED.get()) { - this.setChargesEnabled(JOption.create("Settings.Charges.Enabled", this.isChargesEnabled(), - "When 'true' enables the Charges system for this enchantment.", - "When enchanted the first time on enchanting table, it will have maximum charges amount.").read(cfg)); - - this.setChargesCustomFuel(JOption.create("Settings.Charges.Custom_Fuel", this.isChargesCustomFuel(), - "When 'true' uses different (non-default) fuel item (from the 'Fuel_Item' setting) to recharge.").read(cfg)); - - this.setChargesMax(EnchantScaler.read(enchant, "Settings.Charges.Maximum", "100", - "Maximum amount of charges for the enchantment.")); - - this.setChargesConsumeAmount(EnchantScaler.read(enchant, "Settings.Charges.Consume_Amount", "1", - "How many charges will be consumed when enchantment is triggered?")); - - this.setChargesRechargeAmount(EnchantScaler.read(enchant, "Settings.Charges.Recharge_Amount", "25", - "How many charges will be restored when using 'Fuel Item' in anvil?")); - - this.setChargesFuel(JOption.create("Settings.Charges.Fuel_Item", new ItemStack(Material.LAPIS_LAZULI), - "An item, that will be used to restore enchantment charges on anvils.", - "Item Options:" + Placeholders.URL_ENGINE_ITEMS) - .setWriter(JYML::setItem).read(cfg)); - } - } - - @NotNull - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(@NotNull String displayName) { - this.displayName = Colorizer.apply(displayName); - } - - @NotNull - public Tier getTier() { - return tier; - } - - public void setTier(double rarity) { - this.setTier(ExcellentEnchantsAPI.getTierManager().getByRarityModifier(rarity)); - } - - public void setTier(@NotNull Tier tier) { - this.tier = tier; - } - - public void setDescription(@NotNull String... description) { - this.setDescription(Arrays.asList(description)); - } - - public void setDescription(@NotNull List description) { - this.description = Colorizer.apply(description); - } - - @NotNull - public List getDescription() { - return description; - } - - public boolean isHiddenFromList() { - return hiddenFromList; - } - - public void setHiddenFromList(boolean hiddenFromList) { - this.hiddenFromList = hiddenFromList; - } - - public boolean isTreasure() { - return isTreasure; - } - - public void setTreasure(boolean treasure) { - isTreasure = treasure; - } - - public boolean isTradeable() { - return tradeable; - } - - public void setTradeable(boolean tradeable) { - this.tradeable = tradeable; - } - - public boolean isDiscoverable() { - return discoverable; - } - - public void setDiscoverable(boolean discoverable) { - this.discoverable = discoverable; - } - - public void setLevelMin(int levelMin) { - this.levelMin = Math.max(1, levelMin); - } - - public int getLevelMin() { - return levelMin; - } - - public void setLevelMax(int levelMax) { - this.levelMax = Math.max(1, levelMax); - } - - public int getLevelMax() { - return levelMax; - } - - public int getMaxMergeLevel() { - return this.maxMergeLevel; - } - - public void setMaxMergeLevel(int maxMergeLevel) { - this.maxMergeLevel = Math.min(this.getLevelMax(), maxMergeLevel); - } - - @NotNull - public EnchantScaler getLevelByEnchantCost() { - return levelByEnchantCost; - } - - public void setLevelByEnchantCost(@NotNull EnchantScaler levelByEnchantCost) { - this.levelByEnchantCost = levelByEnchantCost; - } - - @NotNull - public EnchantScaler getAnvilMergeCost() { - return anvilMergeCost; - } - - public void setAnvilMergeCost(@NotNull EnchantScaler anvilMergeCost) { - this.anvilMergeCost = anvilMergeCost; - } - - @NotNull - public Map getObtainChance() { - return obtainChance; - } - - @NotNull - public Map getObtainLevelCap() { - return obtainLevelCap; - } - - public void setConflicts(@NotNull String... conflicts) { - this.setConflicts(new HashSet<>(Arrays.asList(conflicts))); - } - - public void setConflicts(@NotNull Set conflicts) { - this.conflicts = conflicts; - } - - @NotNull - public Set getConflicts() { - return conflicts; - } - - public boolean isVisualEffects() { - return visualEffects; - } - - public void setVisualEffects(boolean visualEffects) { - this.visualEffects = visualEffects; - } - - public boolean isChargesEnabled() { - return chargesEnabled; - } - - public void setChargesEnabled(boolean chargesEnabled) { - this.chargesEnabled = chargesEnabled; - } - - public boolean isChargesCustomFuel() { - return chargesCustomFuel; - } - - public void setChargesCustomFuel(boolean chargesCustomFuel) { - this.chargesCustomFuel = chargesCustomFuel; - } - - @NotNull - public EnchantScaler getChargesMax() { - return chargesMax; - } - - public void setChargesMax(@NotNull EnchantScaler chargesMax) { - this.chargesMax = chargesMax; - } - - @Nullable - public ItemStack getChargesFuel() { - return chargesFuel; - } - - public void setChargesFuel(@Nullable ItemStack chargesFuel) { - this.chargesFuel = chargesFuel; - } - - @NotNull - public EnchantScaler getChargesConsumeAmount() { - return chargesConsumeAmount; - } - - public void setChargesConsumeAmount(@NotNull EnchantScaler chargesConsumeAmount) { - this.chargesConsumeAmount = chargesConsumeAmount; - } - - @NotNull - public EnchantScaler getChargesRechargeAmount() { - return chargesRechargeAmount; - } - - public void setChargesRechargeAmount(@NotNull EnchantScaler chargesRechargeAmount) { - this.chargesRechargeAmount = chargesRechargeAmount; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/config/EnchantScaler.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/config/EnchantScaler.java deleted file mode 100644 index 99c0ac6..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/config/EnchantScaler.java +++ /dev/null @@ -1,80 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.config; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.utils.Evaluator; -import su.nexmedia.engine.utils.StringUtil; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; - -import java.util.*; - -public class EnchantScaler { - - public EnchantScaler(@NotNull ExcellentEnchant enchant, @NotNull String path) { - this(enchant.getConfig(), path, Placeholders.ENCHANTMENT_LEVEL, enchant.getStartLevel(), enchant.getMaxLevel()); - } - - @NotNull - public static EnchantScaler read(@NotNull ExcellentEnchant enchant, @NotNull String path, @NotNull String def, @Nullable String... comments) { - enchant.getConfig().addMissing(path, def); - if (comments != null) { - List list = new ArrayList<>(Arrays.asList(comments)); - list.add("You can use formulas/expressions here: " + Placeholders.URL_ENGINE_SCALER); - list.add("Level placeholder: " + Placeholders.ENCHANTMENT_LEVEL); - enchant.getConfig().setComments(path, list); - } - return new EnchantScaler(enchant, path); - } - - private final int levelMin; - private final int levelMax; - private final TreeMap values; - - public EnchantScaler(@NotNull JYML cfg, @NotNull String path, @NotNull String levelPlaceholder, int levelMin, int levelMax) { - this.levelMin = levelMin; - this.levelMax = levelMax; - this.values = new TreeMap<>(); - - // Load different values for each object level. - Set lvlKeys = cfg.getSection(path); - if (!lvlKeys.isEmpty()) { - for (String sLvl : lvlKeys) { - int eLvl = StringUtil.getInteger(sLvl, 0); - if (eLvl < this.getLevelMin() || eLvl > this.getLevelMax()) continue; - - String formula = cfg.getString(path + "." + sLvl, "0").replace(levelPlaceholder, sLvl); - values.put(eLvl, Evaluator.evaluate(formula)); - } - return; - } - - // Load the single formula for all object levels. - for (int lvl = this.getLevelMin(); lvl < (this.getLevelMax() + 1); lvl++) { - String sLvl = String.valueOf(lvl); - String exChance = cfg.getString(path, "").replace(levelPlaceholder, sLvl); - if (exChance.isEmpty()) continue; - - values.put(lvl, Evaluator.evaluate(exChance)); - } - } - - public int getLevelMin() { - return this.levelMin; - } - - public int getLevelMax() { - return this.levelMax; - } - - @NotNull - public TreeMap getValues() { - return this.values; - } - - public double getValue(int level) { - Map.Entry en = this.values.floorEntry(level); - return en != null ? en.getValue() : 0D; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/AbstractEnchantmentData.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/AbstractEnchantmentData.java new file mode 100644 index 0000000..2091bc5 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/AbstractEnchantmentData.java @@ -0,0 +1,738 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.distribution.DistributionOptions; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.enchantment.util.EnchantPlaceholders; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.language.LangAssets; +import su.nightexpress.nightcore.manager.AbstractFileData; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.ItemUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.PDCUtil; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.placeholder.PlaceholderMap; +import su.nightexpress.nightcore.util.random.Rnd; + +import java.io.File; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public abstract class AbstractEnchantmentData extends AbstractFileData implements EnchantmentData { + + protected Enchantment enchantment; + + private Rarity rarity; + private String displayName; + private List description; + + private boolean hiddenFromList; + private boolean treasure; + private boolean visualEffects; + + private int minLevel; + private int maxLevel; + //private int maxMergeLevel; + + private Modifier minCost; + private Modifier maxCost; + //private Modifier anvilMergeCost; + + private boolean chargesEnabled; + private boolean chargesCustomFuel; + private Modifier chargesMax; + private Modifier chargesConsumeAmount; + private Modifier chargesRechargeAmount; + private ItemStack chargesFuel; + + private final DistributionOptions distributionOptions; + private final Set conflicts; + private final NamespacedKey chargesKey; + private final EnchantPlaceholders placeholders; + + public AbstractEnchantmentData(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(new ArrayList<>()); + this.setRarity(Rarity.COMMON); + this.setStartLevel(1); + this.setMaxLevel(3); + + this.conflicts = new HashSet<>(); + this.chargesKey = new NamespacedKey(plugin, this.getId() + ".charges"); + this.placeholders = new EnchantPlaceholders(); + + if (!Config.isVanillaDistribution()) { + this.distributionOptions = new CustomDistribution(this); + } + else { + this.distributionOptions = new VanillaDistribution(); + } + } + + public void registerListeners() { + if (this instanceof SimpeListener listener) { + this.plugin.getPluginManager().registerEvents(listener, plugin); + } + } + + @Override + public boolean checkServerRequirements() { + return true; + } + + @Override + protected boolean onLoad(@NotNull FileConfig cfg) { + this.setRarity(ConfigValue.create("Settings.Rarity", Rarity.class, this.rarity, + "The rarity is an attribute of an enchantment.", + "It affects the chance of getting an enchantment from enchanting or loots as well as the combination cost in anvil." + ).read(cfg)); + + this.setDisplayName(ConfigValue.create("Settings.Name", + StringUtil.capitalizeUnderscored(this.getId()), + "Enchantment name." + ).read(cfg)); + + this.setDescription(ConfigValue.create("Settings.Description", + this.getDescription(), + "Enchantment description.", + "You can use 'Enchantment' placeholders: " + URL_PLACEHOLDERS + ).read(cfg)); + + this.setStartLevel(ConfigValue.create("Settings.Level.Min", + this.getMinLevel(), + "Min. enchantment level." + ).read(cfg)); + + this.setMaxLevel(ConfigValue.create("Settings.Level.Max", + this.getMaxLevel(), + "Max. enchantment level." + ).read(cfg)); + + this.setHiddenFromList(ConfigValue.create("Settings.Hide_From_List", + false, + "Sets whether or not this enchantment will be hidden from Enchants GUI." + ).read(cfg)); + + this.setConflicts(ConfigValue.create("Settings.Conflicts", + this.getConflicts(), + "Makes this enchantment exclusive for ones in the list.", + "Conflicting enchantments can not be combined on anvils and obtained together on the same item." + ).read(cfg)); + + this.setVisualEffects(ConfigValue.create("Settings.VisualEffects.Enabled", + true, + "Enables enchantment visual effects (mostly particles)." + ).read(cfg)); + + + + this.setTreasure(ConfigValue.create("Distribution.Treasure", + false, + "Sets whether this enchantment is a treasure enchantment.", + "Treasure enchantments can only be received via looting, trading, or fishing." + ).read(cfg)); + + //int costAdjust = Math.max(7, 42 - this.getMaxLevel() * 7); + double costBase = Config.isVanillaDistribution() ? 45D : 30D; + double costAdjust = costBase / this.getMaxLevel(); + + this.setMinCost(Modifier.read(cfg, "Distribution." + DistributionWay.ENCHANTING.getPathName() + ".Min_Cost", + Modifier.add(1 - costAdjust, costAdjust, 1), + VANILLA_DISTRIBUTION_HEADER, + "Sets min. **modified** level cost for this enchantment to be selected in enchanting table.", + "Explanation: https://minecraft.wiki/w/Enchanting_mechanics#How_enchantments_are_chosen", + "Vanilla costs: https://minecraft.wiki/w/Enchanting/Levels", + CUSTOM_DISTRIBUTION_HEADER, + "Sets min. **plain** level cost for this enchantment to be selected in enchanting table.") + ); + + this.setMaxCost(Modifier.read(cfg, "Distribution." + DistributionWay.ENCHANTING.getPathName() + ".Max_Cost", + Modifier.add(12 - costAdjust, costAdjust, 1), + VANILLA_DISTRIBUTION_HEADER, + "Sets max. **modified** level cost for this enchantment to be selected in enchanting table.", + "Explanation: https://minecraft.wiki/w/Enchanting_mechanics#How_enchantments_are_chosen", + "Vanilla costs: https://minecraft.wiki/w/Enchanting/Levels", + CUSTOM_DISTRIBUTION_HEADER, + "Sets max. **plain** level cost for this enchantment to be selected in enchanting table.") + ); + + this.distributionOptions.load(cfg); + + + + /*this.setAnvilMergeCost(Modifier.read(cfg, "Anvil.Merge.Cost", + Modifier.add(1, 1, 1), + "Sets XP cost to apply or transfer this enchantment using anvils." + )); + + this.setMaxMergeLevel(ConfigValue.create("Anvil.Merge.Max_Level", + -1, + "Max. enchantment level that can be obtained by combining 2 items with this enchantment.", + "Set to '-1' to remove limit and cap to max. enchantment level." + ).read(cfg));*/ + + + + if (Config.ENCHANTMENTS_CHARGES_ENABLED.get() && !this.isCurse()) { + this.setChargesEnabled(ConfigValue.create("Charges.Enabled", + false, + "When 'true' enables the Charges system for this enchantment.", + "[*] Enchantments in enchanting table are generated with maximum charges." + ).read(cfg)); + + this.setChargesCustomFuel(ConfigValue.create("Charges.Custom_Fuel", + false, + "When 'true' uses different (non-default) fuel item (from the 'Fuel_Item' setting) to recharge." + ).read(cfg)); + + this.setChargesMax(Modifier.read(cfg, "Charges.Maximum", + Modifier.add(100, 25, 1), + "Maximum amount of charges for the enchantment." + )); + + this.setChargesConsumeAmount(Modifier.read(cfg, "Charges.Consume_Amount", + Modifier.add(1, 0, 0), + "How many charges will be consumed when enchantment is triggered?" + )); + + this.setChargesRechargeAmount(Modifier.read(cfg, "Charges.Recharge_Amount", + Modifier.add(25, 5, 1), + "How many charges will be restored when using 'Fuel Item' in anvil?" + )); + + this.setChargesFuel(ConfigValue.create("Charges.Fuel_Item", + new ItemStack(Material.LAPIS_LAZULI), + "An item, that will be used to restore enchantment charges on anvils.", + WIKI_ITEMS_URL + ).read(cfg)); + } + + this.placeholders + .add(ENCHANTMENT_ID, this::getId) + .add(ENCHANTMENT_NAME, this::getName) + .add(ENCHANTMENT_NAME_FORMATTED, this::getNameFormatted) + .add(ENCHANTMENT_DESCRIPTION, () -> String.join("\n", this.getDescription())) + .add(ENCHANTMENT_DESCRIPTION_FORMATTED, () -> String.join("\n", this.getDescriptionFormatted())) + .add(ENCHANTMENT_DESCRIPTION_REPLACED, level -> String.join("\n", this.getDescriptionReplaced(level))) + .add(ENCHANTMENT_LEVEL, NumberUtil::toRoman) + .add(ENCHANTMENT_LEVEL_MIN, () -> String.valueOf(this.getMinLevel())) + .add(ENCHANTMENT_LEVEL_MAX, () -> String.valueOf(this.getMaxLevel())) + .add(ENCHANTMENT_RARITY, () -> plugin.getLangManager().getEnum(this.getRarity())) + .add(ENCHANTMENT_FIT_ITEM_TYPES, () -> { + if (this.getItemCategories().length == 0) return plugin.getLangManager().getEnum(this.getCategory()); + + return String.join(", ", Stream.of(this.getItemCategories()).map(type -> plugin.getLangManager().getEnum(type)).toList()); + }) + .add(ENCHANTMENT_CHARGES_MAX_AMOUNT, level -> NumberUtil.format(this.getChargesMax(level))) + .add(ENCHANTMENT_CHARGES_CONSUME_AMOUNT, level -> NumberUtil.format(this.getChargesConsumeAmount(level))) + .add(ENCHANTMENT_CHARGES_RECHARGE_AMOUNT, level -> NumberUtil.format(this.getChargesRechargeAmount(level))) + .add(ENCHANTMENT_CHARGES_FUEL_ITEM, () -> ItemUtil.getItemName(this.getChargesFuel())); + if (this instanceof ChanceData chanceData) { + this.placeholders.add(ENCHANTMENT_CHANCE, level -> NumberUtil.format(chanceData.getTriggerChance(level))); + } + if (this instanceof PeriodicData periodicData) { + this.placeholders.add(ENCHANTMENT_INTERVAL, () -> NumberUtil.format(periodicData.getInterval() / 20D)); + } + if (this instanceof PotionData potionData) { + this.placeholders.add(ENCHANTMENT_POTION_LEVEL, level -> NumberUtil.toRoman(potionData.getEffectAmplifier(level))); + this.placeholders.add(ENCHANTMENT_POTION_DURATION, level -> NumberUtil.format(potionData.getEffectDuration(level) / 20D)); + this.placeholders.add(ENCHANTMENT_POTION_TYPE, () -> LangAssets.get(potionData.getEffectType())); + } + if (this.getDistributionOptions() instanceof CustomDistribution distribution) { + this.placeholders.add(ENCHANTMENT_OBTAIN_CHANCE_ENCHANTING, () -> NumberUtil.format(distribution.getWeight(DistributionWay.ENCHANTING))); + this.placeholders.add(ENCHANTMENT_OBTAIN_CHANCE_VILLAGER, () -> NumberUtil.format(distribution.getWeight(DistributionWay.VILLAGER))); + this.placeholders.add(ENCHANTMENT_OBTAIN_CHANCE_LOOT_GENERATION, () -> NumberUtil.format(distribution.getWeight(DistributionWay.LOOT_GENERATION))); + this.placeholders.add(ENCHANTMENT_OBTAIN_CHANCE_FISHING, () -> NumberUtil.format(distribution.getWeight(DistributionWay.FISHING))); + this.placeholders.add(ENCHANTMENT_OBTAIN_CHANCE_MOB_SPAWNING, () -> NumberUtil.format(distribution.getWeight(DistributionWay.MOB_EQUIPMENT))); + } + + this.loadAdditional(cfg); + this.registerListeners(); + return true; + } + + protected abstract void loadAdditional(@NotNull FileConfig config); + + @Override + protected void onSave(@NotNull FileConfig cfg) { + + } + + @NotNull + private String logPrefix() { + return "[" + this.getId() + "] "; + } + + protected void info(@NotNull String text) { + this.plugin.info(this.logPrefix() + text); + } + + protected void warn(@NotNull String text) { + this.plugin.warn(this.logPrefix() + text); + } + + protected void error(@NotNull String text) { + this.plugin.error(this.logPrefix() + text); + } + + @NotNull + public PlaceholderMap getPlaceholders(int level) { + return this.placeholders.toMap(level); + } + + public void addPlaceholder(@NotNull String key, @NotNull Function replacer) { + this.placeholders.add(key, replacer); + } + + @Override + @NotNull + public ItemCategory[] getItemCategories() { + return new ItemCategory[0]; + } + + @Override + public EquipmentSlot[] getSlots() { + return switch (this.getCategory()) { + case BOW, CROSSBOW, TRIDENT, FISHING_ROD, WEAPON, TOOL -> new EquipmentSlot[]{EquipmentSlot.HAND}; + case ARMOR_HEAD -> new EquipmentSlot[]{EquipmentSlot.HEAD}; + case ARMOR_TORSO -> new EquipmentSlot[]{EquipmentSlot.CHEST}; + case ARMOR_LEGS -> new EquipmentSlot[]{EquipmentSlot.LEGS}; + case ARMOR_FEET -> new EquipmentSlot[]{EquipmentSlot.FEET}; + case ARMOR, WEARABLE -> new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; + case BREAKABLE -> new EquipmentSlot[]{EquipmentSlot.HAND, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; + case VANISHABLE -> EquipmentSlot.values(); + default -> throw new IllegalStateException("Unexpected value: " + this.getCategory()); + }; + } + + @Override + public boolean isAvailableToUse(@NotNull World world) { + Set disabled = Config.ENCHANTMENTS_DISABLED_IN_WORLDS.get().getOrDefault(world.getName().toLowerCase(), Collections.emptySet()); + return disabled.isEmpty() || (!disabled.contains(this.getId()) && !disabled.contains(WILDCARD)); + } + + @Override + public boolean isAvailableToUse(@NotNull LivingEntity entity) { + return this.isAvailableToUse(entity.getWorld()); + } + + @Override + public final boolean checkEnchantCategory(@NotNull ItemStack item) { + EnchantmentTarget category = this.getCategory(); + + if (category == EnchantmentTarget.WEAPON && ItemUtil.isAxe(item)) { + return Config.CORE_SWORD_ENCHANTS_TO_AXES.get(); + } + if (category == EnchantmentTarget.BOW && item.getType() == Material.CROSSBOW) { + return Config.CORE_BOW_ENCHANTS_TO_CROSSBOW.get(); + } + if ((category == EnchantmentTarget.ARMOR || category == EnchantmentTarget.ARMOR_TORSO) && item.getType() == Material.ELYTRA) { + return Config.CORE_CHESTPLATE_ENCHANTS_TO_ELYTRA.get(); + } + return false; + } + + @Override + public boolean checkItemCategory(@NotNull ItemStack item) { + ItemCategory[] itemCategories = this.getItemCategories(); + if (itemCategories.length == 0) return false; + + return Stream.of(itemCategories).anyMatch(itemCategory -> itemCategory.isIncluded(item)); + } + + public int generateLevel() { + return Rnd.get(this.getMinLevel(), this.getMaxLevel()); + } + + @Override + @NotNull + public String getNameFormatted(int level, int charges) { + String rarityFormat = this.isCurse() ? Config.ENCHANTMENTS_DISPLAY_NAME_CURSE_FORMAT.get() : Config.ENCHANTMENTS_DISPLAY_NAME_RARITY_FORMAT.get().getOrDefault(this.getRarity(), GENERIC_NAME); + String chargesFormat = ""; + boolean showLevel = !Config.ENCHANTMENTS_DISPLAY_NAME_HIDE_1ST_LEVEL.get() || level > 1; + boolean showCharges = this.isChargesEnabled() && charges >= 0; + + if (showCharges) { + int chargesMax = this.getChargesMax(level); + int percent = (int) Math.ceil((double) charges / (double) chargesMax * 100D); + Map.Entry entry = Config.ENCHANTMENTS_CHARGES_FORMAT.get().floorEntry(percent); + if (entry != null) { + chargesFormat = entry.getValue().replace(GENERIC_AMOUNT, String.valueOf(charges)); + } + } + + String compName = Config.ENCHANTMENTS_DISPLAY_NAME_COMPONENT_NAME.get().replace(GENERIC_VALUE, this.getName()); + String compLevel = showLevel ? Config.ENCHANTMENTS_DISPLAY_NAME_COMPONENT_LEVEL.get().replace(GENERIC_VALUE, NumberUtil.toRoman(level)) : ""; + String compChrages = showCharges ? Config.ENCHANTMENTS_DISPLAY_NAME_COMPONENT_CHARGES.get().replace(GENERIC_VALUE, chargesFormat) : ""; + + String nameFormat = Config.ENCHANTMENTS_DISPLAY_NAME_FORMAT.get(). + replace(ENCHANTMENT_NAME, compName) + .replace(ENCHANTMENT_LEVEL, compLevel) + .replace(ENCHANTMENT_CHARGES, compChrages); + + return rarityFormat.replace(GENERIC_NAME, nameFormat); + } + + @Override + @NotNull + public List getDescriptionFormatted() { + return new ArrayList<>(this.getDescription().stream() + .map(line -> Config.ENCHANTMENTS_DISPLAY_DESCRIPTION_FORMAT.get().replace(GENERIC_DESCRIPTION, line)) + .toList()); + } + + @Override + @NotNull + public List getDescriptionReplaced(int level) { + List description = new ArrayList<>(this.getDescriptionFormatted()); + description.replaceAll(this.getPlaceholders(level).replacer()); + return description; + } + + @Override + public int getMinCost(int level) { + return this.getMinCost().getIntValue(level); + } + + @Override + public int getMaxCost(int level) { + return this.getMaxCost().getIntValue(level); + } + + /*@Override + public int getAnvilMergeCost(int level) { + return this.getAnvilMergeCost().getIntValue(level); + }*/ + + @Override + public int getChargesMax(int level) { + return this.isChargesEnabled() ? this.getChargesMax().getIntValue(level) : 0; + } + + @Override + public int getChargesConsumeAmount(int level) { + return this.isChargesEnabled() ? this.getChargesConsumeAmount().getIntValue(level) : 0; + } + + @Override + public int getChargesRechargeAmount(int level) { + return this.isChargesEnabled() ? this.getChargesRechargeAmount().getIntValue(level) : 0; + } + + @Override + public boolean isChargesFuel(@NotNull ItemStack item) { + if (Config.ENCHANTMENTS_CHARGES_COMPARE_TYPE_ONLY.get()) { + return item.getType() == this.getChargesFuel().getType(); + } + return item.isSimilar(this.getChargesFuel()); + } + + @Override + public boolean isOutOfCharges(@NotNull ItemStack item) { + return this.getCharges(item) == 0; + } + + @Override + public boolean isFullOfCharges(@NotNull ItemStack item) { + if (!this.isChargesEnabled()) return true; + + int level = EnchantUtils.getLevel(item, this.getEnchantment()); + int max = this.getChargesMax(level); + + return this.getCharges(item) == max; + } + + @Override + public int getCharges(@NotNull ItemMeta meta) { + return this.isChargesEnabled() ? PDCUtil.getInt(meta, this.chargesKey).orElse(0) : -1; + } + + @Override + public void setCharges(@NotNull ItemStack item, int level, int amount) { + if (!this.isChargesEnabled()) return; + + int max = this.getChargesMax(level); + int set = Math.min(Math.abs(amount), max); + PDCUtil.set(item, this.chargesKey, set); + } + + @Override + public void restoreCharges(@NotNull ItemStack item, int level) { + this.setCharges(item, level, Integer.MAX_VALUE); + } + + @Override + public void fuelCharges(@NotNull ItemStack item, int level) { + int recharge = this.getChargesRechargeAmount(level); + + int has = this.getCharges(item); + int set = has + recharge; + + this.setCharges(item, level, set); + } + + @Override + public void consumeChargesNoUpdate(@NotNull ItemStack item, int level) { + if (!this.isChargesEnabled()) return; + + int charges = this.getCharges(item); + int consumeAmount = this.getChargesConsumeAmount(level); + + this.setCharges(item, level, charges < consumeAmount ? 0 : Math.max(0, charges - consumeAmount)); + } + + @Override + public void consumeCharges(@NotNull ItemStack item, int level) { + if (!this.isChargesEnabled()) return; + + this.consumeChargesNoUpdate(item, level); + EnchantUtils.updateDisplay(item); + } + + @Override + @NotNull + public Enchantment getEnchantment() { + return this.enchantment; + } + + @Override + public void setEnchantment(@NotNull Enchantment enchantment) { + this.enchantment = enchantment; + } + + @NotNull + @Override + public Rarity getRarity() { + return rarity; + } + + @Override + public void setRarity(@NotNull Rarity rarity) { + this.rarity = rarity; + } + + @NotNull + @Override + public DistributionOptions getDistributionOptions() { + return distributionOptions; + } + + @NotNull + public String getName() { + return displayName; + } + + @Override + public void setDisplayName(@NotNull String displayName) { + this.displayName = displayName; + } + + @Override + @NotNull + public List getDescription() { + return description; + } + + @Override + public void setDescription(@NotNull List description) { + this.description = description; + } + + @Override + public boolean isHiddenFromList() { + return hiddenFromList; + } + + @Override + public void setHiddenFromList(boolean hiddenFromList) { + this.hiddenFromList = hiddenFromList; + } + + @Override + public boolean isTreasure() { + return this.treasure; + } + + @Override + public void setTreasure(boolean treasure) { + this.treasure = treasure; + } + + @Override + public void setStartLevel(int levelMin) { + this.minLevel = Math.max(1, levelMin); + } + + @Override + public int getMinLevel() { + return this.minLevel; + } + + @Override + public void setMaxLevel(int levelMax) { + this.maxLevel = Math.max(1, levelMax); + } + + @Override + public int getMaxLevel() { + return maxLevel; + } + + @Override + @NotNull + public Modifier getMinCost() { + return this.minCost; + } + + @Override + public void setMinCost(@NotNull Modifier minCost) { + this.minCost = minCost; + } + + @Override + @NotNull + public Modifier getMaxCost() { + return this.maxCost; + } + + @Override + public void setMaxCost(@NotNull Modifier maxCost) { + this.maxCost = maxCost; + } + + /*@Override + @NotNull + public Modifier getAnvilMergeCost() { + return this.anvilMergeCost; + } + + @Override + public void setAnvilMergeCost(@NotNull Modifier anvilMergeCost) { + this.anvilMergeCost = anvilMergeCost; + } + + @Override + public int getMaxMergeLevel() { + return this.maxMergeLevel; + } + + @Override + public void setMaxMergeLevel(int maxMergeLevel) { + this.maxMergeLevel = Math.min(this.getMaxLevel(), maxMergeLevel); + }*/ + + @Override + @NotNull + public Set getConflicts() { + return this.conflicts; + } + + @Override + public void setConflicts(@NotNull Set conflicts) { + this.conflicts.clear(); + this.conflicts.addAll(conflicts.stream().map(String::toLowerCase).collect(Collectors.toSet())); + } + + @Override + public boolean hasVisualEffects() { + return visualEffects; + } + + @Override + public void setVisualEffects(boolean visualEffects) { + this.visualEffects = visualEffects; + } + + @Override + public boolean isChargesEnabled() { + return chargesEnabled; + } + + @Override + public void setChargesEnabled(boolean chargesEnabled) { + this.chargesEnabled = chargesEnabled; + } + + @Override + public boolean isChargesCustomFuel() { + return chargesCustomFuel; + } + + @Override + public void setChargesCustomFuel(boolean chargesCustomFuel) { + this.chargesCustomFuel = chargesCustomFuel; + } + + @Override + @NotNull + public Modifier getChargesMax() { + return chargesMax; + } + + @Override + public void setChargesMax(@NotNull Modifier chargesMax) { + this.chargesMax = chargesMax; + } + + @NotNull + public ItemStack getChargesFuel() { + ItemStack fuelHas = this.chargesFuel; + if (!this.isChargesCustomFuel() || fuelHas == null || fuelHas.getType().isAir()) { + return new ItemStack(Config.ENCHANTMENTS_CHARGES_FUEL_ITEM.get()); + } + return new ItemStack(fuelHas); + } + + @Override + public void setChargesFuel(@Nullable ItemStack chargesFuel) { + this.chargesFuel = chargesFuel; + } + + @Override + @NotNull + public Modifier getChargesConsumeAmount() { + return chargesConsumeAmount; + } + + @Override + public void setChargesConsumeAmount(@NotNull Modifier chargesConsumeAmount) { + this.chargesConsumeAmount = chargesConsumeAmount; + } + + @Override + @NotNull + public Modifier getChargesRechargeAmount() { + return chargesRechargeAmount; + } + + @Override + public void setChargesRechargeAmount(@NotNull Modifier chargesRechargeAmount) { + this.chargesRechargeAmount = chargesRechargeAmount; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/ArrowSettingsImpl.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/ArrowSettingsImpl.java new file mode 100644 index 0000000..fca338c --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/ArrowSettingsImpl.java @@ -0,0 +1,42 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.bukkit.Particle; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowSettings; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +public class ArrowSettingsImpl implements ArrowSettings { + + //private final EnchantmentData enchantmentData; + private final UniParticle trailParticle; + + private ArrowSettingsImpl(@NotNull UniParticle trailParticle) { + //this.enchantmentData = enchantmentData; + this.trailParticle = trailParticle; + } + + @NotNull + public static ArrowSettingsImpl create(@NotNull FileConfig config) { + return create(config, UniParticle.of(Particle.REDSTONE)); + } + + @NotNull + public static ArrowSettingsImpl create(@NotNull FileConfig config, @NotNull UniParticle particle) { + UniParticle effect = ConfigValue.create("Settings.VisualEffects.Trail", + (cfg, path, def) -> UniParticle.read(cfg, path), + (cfg, path, particle1) -> particle1.write(cfg, path), + () -> particle, + "Sets projectile particle trail effect." + ).read(config); + + return new ArrowSettingsImpl(effect); + } + + @Override + @NotNull + public UniParticle getProjectileTrail() { + return this.trailParticle; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/ChanceSettingsImpl.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/ChanceSettingsImpl.java new file mode 100644 index 0000000..090ac33 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/ChanceSettingsImpl.java @@ -0,0 +1,39 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.random.Rnd; + +public class ChanceSettingsImpl implements ChanceSettings { + + private final Modifier triggerChance; + + private ChanceSettingsImpl(@NotNull Modifier triggerChance) { + this.triggerChance = triggerChance; + } + + @NotNull + public static ChanceSettingsImpl create(@NotNull FileConfig config) { + return create(config, Modifier.add(100, 0, 1, 100)); + } + + @NotNull + public static ChanceSettingsImpl create(@NotNull FileConfig config, @NotNull Modifier def) { + Modifier chanceMod = Modifier.read(config, "Settings.Trigger_Chance", def, + "A chance that this enchantment will be triggered."); + + return new ChanceSettingsImpl(chanceMod); + } + + @Override + public double getTriggerChance(int level) { + return this.triggerChance.getValue(level); + } + + @Override + public boolean checkTriggerChance(int level) { + return Rnd.chance(this.getTriggerChance(level)); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/CustomDistribution.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/CustomDistribution.java new file mode 100644 index 0000000..9c72279 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/CustomDistribution.java @@ -0,0 +1,154 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.bukkit.loot.LootTable; +import org.bukkit.loot.LootTables; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.enchantment.distribution.DistributionOptions; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.random.Rnd; +import su.nightexpress.nightcore.util.wrapper.UniInt; + +import java.util.*; + +public class CustomDistribution implements DistributionOptions { + + private final EnchantmentData enchantmentData; + + private final Map weightMap; + private final Map levelRangeMap; + private final Set lootTables; + + public CustomDistribution(@NotNull EnchantmentData enchantmentData) { + this.enchantmentData = enchantmentData; + + this.weightMap = new HashMap<>(); + this.levelRangeMap = new HashMap<>(); + this.lootTables = new HashSet<>(); + } + + public void load(@NotNull FileConfig config) { + for (DistributionWay distributionWay : DistributionWay.values()) { + String pathName = distributionWay.getPathName(); + + double obtainChance = ConfigValue.create("Distribution." + pathName + ".Weight", 50D, + "Determines how often this enchantment will appear in " + pathName + ".", + "Greater value = Greater chance.").read(config); + + this.weightMap.put(distributionWay, obtainChance); + + int levelMin = ConfigValue.create("Distribution." + pathName + ".Level.Min", -1, + "Minimal level when obtained via " + pathName, + "Can not be less than enchantment min. level. Set -1 to use enchantment min. level.").read(config); + + int levelMax = ConfigValue.create("Distribution." + pathName + ".Level.Max", -1, + "Maximal level when obtained via " + pathName, + "Can not be greater than enchantment max. level. Set -1 to use enchantment max. level.").read(config); + + this.levelRangeMap.put(distributionWay, UniInt.of(levelMin, levelMax)); + } + + boolean isWhitelist = ConfigValue.create("Distribution." + DistributionWay.LOOT_GENERATION.getPathName() + ".LootTables.Whitelist", + false, + "When 'true', uses only loot tables listed below.", + "When 'false', uses ALL loot tables except ones listed below.", + "[Default is false]" + ).read(config); + + Set tables = ConfigValue.forSet("Distribution." + DistributionWay.LOOT_GENERATION.getPathName() + ".LootTables.List", + id -> StringUtil.getEnum(id, LootTables.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of( + LootTables.DESERT_PYRAMID + ), + "Depends on Whitelist mode, this enchantment will appear on items generated by certain Loot Tables only.", + "=".repeat(15) + " EXAMPLES " + "=".repeat(15), + "==> Set 'Whitelist' on 'true' and add '" + LootTables.DESERT_PYRAMID.name() + "' to the list to make this enchantment appear on items generated inside Desert Pyramid chests only.", + "==> Set 'Whitelist' on 'false' and add '" + LootTables.DESERT_PYRAMID.name() + "' to the list to make this enchantment appear on items generated inside any structure's chests except Deset Pyramids.", + "", + "[*] Keep in mind, that Loot Generation is only applicable to items in chests. Listing here loot tables of mobs, fishing and other sources is useless.", + "Available loot table names: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/loot/LootTables.html" + ).read(config); + + if (isWhitelist) { + this.lootTables.addAll(tables); + } + else { + this.lootTables.addAll(Arrays.asList(LootTables.values())); + this.lootTables.removeAll(tables); + } + } + + @NotNull + public Map getWeightMap() { + return weightMap; + } + + @NotNull + public Map getLevelRangeMap() { + return levelRangeMap; + } + + @NotNull + public Set getLootTables() { + return lootTables; + } + + public boolean isDistributable(@NotNull DistributionWay distributionWay) { + if (distributionWay == DistributionWay.ENCHANTING && (this.enchantmentData.isTreasure() || this.enchantmentData.isCurse())) return false; + + return this.getWeight(distributionWay) > 0D; + } + + public boolean isGoodLootTable(@NotNull LootTable table) { + return this.getLootTables().stream().anyMatch(tables -> tables.getLootTable() == table); + } + + public double getWeight(@NotNull DistributionWay distributionWay) { + return this.getWeightMap().getOrDefault(distributionWay, 0D); + } + + public int getMinLevel(@NotNull DistributionWay distributionWay) { + return this.getLevelRangeMap().getOrDefault(distributionWay, UniInt.of(-1, -1)).getMinValue(); + } + + public int getMaxLevel(@NotNull DistributionWay distributionWay) { + return this.getLevelRangeMap().getOrDefault(distributionWay, UniInt.of(-1, -1)).getMaxValue(); + } + + public int generateLevel(@NotNull DistributionWay distributionWay) { + int levelCapMin = this.getMinLevel(distributionWay); + int levelCapMax = this.getMaxLevel(distributionWay); + + if (levelCapMin <= 0 || levelCapMin < this.enchantmentData.getMinLevel()) levelCapMin = this.enchantmentData.getMinLevel(); + if (levelCapMax <= 0 || levelCapMax > this.enchantmentData.getMaxLevel()) levelCapMax = this.enchantmentData.getMaxLevel(); + + return Rnd.get(levelCapMin, levelCapMax); + } + + public int getLevelByEnchantCost(int xpLevel) { + int get = 0; + + for (int level = this.enchantmentData.getMaxLevel(); level > this.enchantmentData.getMinLevel() - 1; level--) { + if (xpLevel >= this.enchantmentData.getMinCost(level) && xpLevel <= this.enchantmentData.getMaxCost(level)) { + get = level; + break; + } + } + + return get != 0 ? this.fineLevel(get, DistributionWay.ENCHANTING) : 0; + } + + public int fineLevel(int level, @NotNull DistributionWay distributionWay) { + int levelCapMin = this.getMinLevel(distributionWay); + int levelCapMax = this.getMaxLevel(distributionWay); + + if (levelCapMin > 0 && level < levelCapMin) level = levelCapMin; + if (levelCapMax > 0 && level > levelCapMax) level = levelCapMax; + + return level; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/PeriodSettingsImpl.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/PeriodSettingsImpl.java new file mode 100644 index 0000000..7f60c38 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/PeriodSettingsImpl.java @@ -0,0 +1,55 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; +import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.nightcore.config.FileConfig; + +public class PeriodSettingsImpl implements PeriodicSettings { + + private final Modifier triggerInterval; + + private long nextTriggerTime; + + public PeriodSettingsImpl(@NotNull Modifier triggerInterval) { + this.triggerInterval = triggerInterval; + this.updateTriggerTime(); + } + + @NotNull + public static PeriodSettingsImpl create(@NotNull FileConfig config) { + long baseTick = Config.CORE_PASSIVE_ENCHANTS_TRIGGER_INTERVAL.get(); + + return create(config, Modifier.add(baseTick, 0, 1)); + } + + @NotNull + public static PeriodSettingsImpl create(@NotNull FileConfig config, @NotNull Modifier def) { + Modifier intervalMod = Modifier.read(config, "Settings.Trigger_Interval", def, + "Sets how often (in ticks) this enchantment will be triggered.", + "20 ticks = 1 second."); + + return new PeriodSettingsImpl(intervalMod); + } + + @Override + public long getInterval() { + return (long) this.triggerInterval.getValue(1); + } + + @Override + public long getNextTriggerTime() { + return nextTriggerTime; + } + + @Override + public boolean isTriggerTime() { + return System.currentTimeMillis() >= this.getNextTriggerTime(); + } + + @Override + public void updateTriggerTime() { + this.nextTriggerTime = System.currentTimeMillis() + this.getInterval() * 50L - 100L; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/PotionSettingsImpl.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/PotionSettingsImpl.java new file mode 100644 index 0000000..f6db99d --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/PotionSettingsImpl.java @@ -0,0 +1,100 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.nightcore.config.FileConfig; + +public class PotionSettingsImpl implements PotionSettings { + + private final PotionEffectType effectType; + private final Modifier duration; + private final Modifier amplifier; + private final boolean isPermanent; + private final boolean particles; + + private PotionSettingsImpl(@NotNull PotionEffectType effectType, + boolean isPermanent, + boolean particles, + @NotNull Modifier duration, + @NotNull Modifier amplifier) { + this.effectType = effectType; + this.duration = duration; + this.amplifier = amplifier; + this.isPermanent = isPermanent; + this.particles = particles; + } + + @NotNull + public static PotionSettingsImpl create(@NotNull EnchantmentData data, @NotNull FileConfig config, @NotNull PotionEffectType type, boolean isPermanent) { + return create(data, config, type, isPermanent, + Modifier.multiply(5, 1, 1), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + public static PotionSettingsImpl create(@NotNull EnchantmentData data, + @NotNull FileConfig config, + @NotNull PotionEffectType type, + boolean isPermanent, + @NotNull Modifier duration, + @NotNull Modifier amplifier) { + + Modifier durationScale = Modifier.read(config, "Settings.Potion_Effect.Duration", duration, + "Potion effect duration (in seconds). This setting is useless for 'permanent' effects."); + + Modifier amplifierScale = Modifier.read(config, "Settings.Potion_Effect.Level", amplifier, + "Potion effect level."); + + return new PotionSettingsImpl(type, isPermanent, data.hasVisualEffects(), durationScale, amplifierScale); + } + + @Override + public boolean isPermanent() { + return this.isPermanent; + } + + @Override + @NotNull + public PotionEffectType getEffectType() { + return this.effectType; + } + + @Override + public int getEffectDuration(int level) { + if (this.isPermanent()) { + int duration = Config.CORE_PASSIVE_ENCHANTS_TRIGGER_INTERVAL.get().intValue() * 2; + if (this.getEffectType().getKey().equals(PotionEffectType.NIGHT_VISION.getKey()) && duration < 600) { + duration += 30 * 20; + } + return duration; + } + return (int) (this.duration.getValue(level) * 20); + } + + @Override + public int getEffectAmplifier(int level) { + return (int) this.amplifier.getValue(level); + } + + @Override + @NotNull + public PotionEffect createEffect(int level) { + int duration = this.getEffectDuration(level); + int amplifier = Math.max(0, this.getEffectAmplifier(level) - 1); + + return new PotionEffect(this.getEffectType(), duration, amplifier, false, this.particles); + } + + @Override + public boolean addEffect(@NotNull LivingEntity target, int level) { + target.addPotionEffect(this.createEffect(level)); + return true; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/VanillaDistribution.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/VanillaDistribution.java new file mode 100644 index 0000000..35a5a5c --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/data/VanillaDistribution.java @@ -0,0 +1,43 @@ +package su.nightexpress.excellentenchants.enchantment.data; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; + +public class VanillaDistribution implements VanillaOptions { + + private boolean discoverable; + private boolean tradeable; + + @Override + public void load(@NotNull FileConfig config) { + this.setTradeable(ConfigValue.create("Distribution.Tradeable", + true, + "Sets whether or not this enchantment can be populated in villager trades.").read(config)); + + this.setDiscoverable(ConfigValue.create("Distribution.Discoverable", + true, + "Sets whether or not this enchantment can be populated in enchanting table.").read(config)); + } + + @Override + public boolean isTradeable() { + return this.tradeable; + } + + @Override + public void setTradeable(boolean tradeable) { + this.tradeable = tradeable; + } + + @Override + public boolean isDiscoverable() { + return discoverable; + } + + @Override + public void setDiscoverable(boolean discoverable) { + this.discoverable = discoverable; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/ExcellentEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/ExcellentEnchant.java deleted file mode 100644 index bcf30da..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/ExcellentEnchant.java +++ /dev/null @@ -1,459 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl; - -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.World; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.api.placeholder.PlaceholderMap; -import su.nexmedia.engine.lang.LangManager; -import su.nexmedia.engine.utils.ItemUtil; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Periodic; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.EnchantManager; -import su.nightexpress.excellentenchants.enchantment.config.EnchantDefaults; -import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; -import su.nightexpress.excellentenchants.tier.Tier; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Stream; - -public abstract class ExcellentEnchant /*extends Enchantment*/ implements IEnchantment { - - protected final ExcellentEnchants plugin; - protected final JYML cfg; - protected final String id; - protected final EnchantDefaults defaults; - protected final NamespacedKey chargesKey; - protected final Map placeholdersMap; - - public ExcellentEnchant(@NotNull ExcellentEnchants plugin, @NotNull String id) { - //super(NamespacedKey.minecraft(id.toLowerCase())); - this.plugin = plugin; - this.id = id.toLowerCase();//this.getKey().getKey(); - this.cfg = new JYML(plugin.getDataFolder() + EnchantManager.DIR_ENCHANTS, id + ".yml"); - this.chargesKey = new NamespacedKey(plugin, this.getId() + ".charges"); - this.defaults = new EnchantDefaults(this); - this.placeholdersMap = new HashMap<>(); - } - - @NotNull - @Override - public NamespacedKey getKey() { - return EnchantUtils.createKey(this.getId()); - } - - public void loadSettings() { - this.cfg.reload(); - this.placeholdersMap.clear(); - - this.getDefaults().load(this); - - for (int i = this.getStartLevel(); i < this.getMaxLevel() + 1; i++) { - int level = i; - - PlaceholderMap map = new PlaceholderMap() - .add(Placeholders.ENCHANTMENT_DESCRIPTION, () -> String.join("\n", this.getDescription())) - .add(Placeholders.ENCHANTMENT_ID, this::getId) - .add(Placeholders.ENCHANTMENT_NAME, this::getDisplayName) - .add(Placeholders.ENCHANTMENT_NAME_FORMATTED, () -> this.getNameFormatted(level)) - .add(Placeholders.ENCHANTMENT_LEVEL, () -> NumberUtil.toRoman(level)) - .add(Placeholders.ENCHANTMENT_LEVEL_MIN, () -> String.valueOf(this.getStartLevel())) - .add(Placeholders.ENCHANTMENT_LEVEL_MAX, () -> String.valueOf(this.getMaxLevel())) - .add(Placeholders.ENCHANTMENT_TIER, () -> this.getTier().getName()) - .add(Placeholders.ENCHANTMENT_TIER_COLOR, () -> this.getTier().getColor()) - .add(Placeholders.ENCHANTMENT_FIT_ITEM_TYPES, () -> { - if (this.getFitItemTypes().length == 0) return plugin.getLangManager().getEnum(this.getCategory()); - - return String.join(", ", Stream.of(this.getFitItemTypes()).map(type -> plugin.getLangManager().getEnum(type)).toList()); - }) - .add(Placeholders.ENCHANTMENT_OBTAIN_CHANCE_ENCHANTING, () -> NumberUtil.format(this.getObtainChance(ObtainType.ENCHANTING))) - .add(Placeholders.ENCHANTMENT_OBTAIN_CHANCE_VILLAGER, () -> NumberUtil.format(this.getObtainChance(ObtainType.VILLAGER))) - .add(Placeholders.ENCHANTMENT_OBTAIN_CHANCE_LOOT_GENERATION, () -> NumberUtil.format(this.getObtainChance(ObtainType.LOOT_GENERATION))) - .add(Placeholders.ENCHANTMENT_OBTAIN_CHANCE_FISHING, () -> NumberUtil.format(this.getObtainChance(ObtainType.FISHING))) - .add(Placeholders.ENCHANTMENT_OBTAIN_CHANCE_MOB_SPAWNING, () -> NumberUtil.format(this.getObtainChance(ObtainType.MOB_SPAWNING))) - .add(Placeholders.ENCHANTMENT_CHARGES_MAX_AMOUNT, () -> NumberUtil.format(this.getChargesMax(level))) - .add(Placeholders.ENCHANTMENT_CHARGES_CONSUME_AMOUNT, () -> NumberUtil.format(this.getChargesConsumeAmount(level))) - .add(Placeholders.ENCHANTMENT_CHARGES_RECHARGE_AMOUNT, () -> NumberUtil.format(this.getChargesRechargeAmount(level))) - .add(Placeholders.ENCHANTMENT_CHARGES_FUEL_ITEM, () -> ItemUtil.getItemName(this.getChargesFuel())); - - if (this instanceof Chanced chanced) { - map.add(Placeholders.ENCHANTMENT_CHANCE, () -> NumberUtil.format(chanced.getTriggerChance(level))); - } - if (this instanceof Periodic periodic) { - map.add(Placeholders.ENCHANTMENT_INTERVAL, () -> NumberUtil.format(periodic.getInterval() / 20D)); - } - if (this instanceof Potioned potioned) { - map.add(Placeholders.ENCHANTMENT_POTION_LEVEL, () -> NumberUtil.toRoman(potioned.getEffectAmplifier(level))); - map.add(Placeholders.ENCHANTMENT_POTION_DURATION, () -> NumberUtil.format(potioned.getEffectDuration(level) / 20D)); - map.add(Placeholders.ENCHANTMENT_POTION_TYPE, () -> LangManager.getPotionType(potioned.getEffectType())); - } - map.add(this.getTier().getPlaceholders()); - - this.placeholdersMap.put(level, map); - } - } - - @NotNull - public PlaceholderMap getPlaceholders(int level) { - if (level > this.getMaxLevel()) level = this.getMaxLevel(); - if (level < this.getStartLevel()) level = this.getStartLevel(); - - return this.placeholdersMap.get(level); - } - - public void addPlaceholder(@NotNull String key, @NotNull Function replacer) { - for (int level = this.getStartLevel(); level < this.getMaxLevel() + 1; level++) { - this.getPlaceholders(level).add(key, replacer.apply(level)); - } - } - - public void registerListeners() { - if (this instanceof EventListener listener) { - this.plugin.getPluginManager().registerEvents(listener, plugin); - } - } - - @NotNull - public ItemCategory[] getFitItemTypes() { - //FitItemType itemType = FitItemType.getByEnchantmentTarget(this.getCategory()); - //return new FitItemType[]{itemType}; - - return new ItemCategory[0]; - } - - @Override - public EquipmentSlot[] getSlots() { - return switch (this.getCategory()) { - case BOW, CROSSBOW, TRIDENT, FISHING_ROD, WEAPON, TOOL -> new EquipmentSlot[]{EquipmentSlot.HAND}; - case ARMOR_HEAD -> new EquipmentSlot[]{EquipmentSlot.HEAD}; - case ARMOR_TORSO -> new EquipmentSlot[]{EquipmentSlot.CHEST}; - case ARMOR_LEGS -> new EquipmentSlot[]{EquipmentSlot.LEGS}; - case ARMOR_FEET -> new EquipmentSlot[]{EquipmentSlot.FEET}; - case ARMOR, WEARABLE -> new EquipmentSlot[]{EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; - case BREAKABLE -> new EquipmentSlot[]{EquipmentSlot.HAND, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET}; - case VANISHABLE -> EquipmentSlot.values(); - default -> throw new IllegalStateException("Unexpected value: " + this.getCategory()); - }; - - /*Set slots = new HashSet<>(); - - for (FitItemType itemType : this.getFitItemTypes()) { - slots.addAll(Arrays.asList(itemType.getSlots())); - } - - return slots.toArray(new EquipmentSlot[0]);*/ - } - - public boolean isDisabledInWorld(@NotNull World world) { - Set disabled = Config.ENCHANTMENTS_DISABLED_IN_WORLDS.get().getOrDefault(world.getName(), Collections.emptySet()); - return disabled.contains(this.getKey().getKey()) || disabled.contains(Placeholders.WILDCARD); - } - - @Override - public boolean isAvailableToUse(@NotNull LivingEntity entity) { - return !this.isDisabledInWorld(entity.getWorld()); - } - - @NotNull - public JYML getConfig() { - return this.cfg; - } - - @NotNull - public String getId() { - return this.id; - } - - @NotNull - public EnchantDefaults getDefaults() { - return defaults; - } - - /*@NotNull - @Override - public String getName() { - return getId().toUpperCase(); - }*/ - - @NotNull - public String getDisplayName() { - return this.getDefaults().getDisplayName(); - } - - @NotNull - public String getNameFormatted(int level) { - String name = this.getTier().getColor() + this.getDisplayName(); - if (level > 1 || this.getMaxLevel() > 1) { - name += " " + NumberUtil.toRoman(level); - } - return name; - } - - @NotNull - public String getNameFormatted(int level, int charges) { - if (!this.isChargesEnabled() || charges < 0) return this.getNameFormatted(level); - - int chargesMax = this.getChargesMax(level); - int percent = (int) Math.ceil((double) charges / (double) chargesMax * 100D); - Map.Entry entry = Config.ENCHANTMENTS_CHARGES_FORMAT.get().floorEntry(percent); - if (entry == null) return this.getNameFormatted(level); - - String format = entry.getValue().replace(Placeholders.GENERIC_AMOUNT, String.valueOf(charges)); - return this.getNameFormatted(level) + " " + format; - } - - @NotNull - public List getDescription() { - return this.getDefaults().getDescription(); - } - - @NotNull - public List getDescription(int level) { - List description = new ArrayList<>(this.getDescription()); - description.replaceAll(this.getPlaceholders(level).replacer()); - return description; - } - - @NotNull - public List formatDescription() { - return new ArrayList<>(this.getDescription().stream() - .map(line -> Config.ENCHANTMENTS_DESCRIPTION_FORMAT.get().replace(Placeholders.GENERIC_DESCRIPTION, line)) - .toList()); - } - - @NotNull - public List formatDescription(int level) { - return new ArrayList<>(this.getDescription(level).stream() - .map(line -> Config.ENCHANTMENTS_DESCRIPTION_FORMAT.get().replace(Placeholders.GENERIC_DESCRIPTION, line)) - .toList()); - } - - public boolean hasConflicts() { - return !this.getConflicts().isEmpty(); - } - - @NotNull - public Set getConflicts() { - return this.getDefaults().getConflicts(); - } - - @NotNull - public Tier getTier() { - return this.getDefaults().getTier(); - } - - @Override - public int getMaxLevel() { - return this.getDefaults().getLevelMax(); - } - - @Override - public int getStartLevel() { - return this.getDefaults().getLevelMin(); - } - - public int getMaxMergeLevel() { - return this.getDefaults().getMaxMergeLevel() < 0 ? this.getMaxLevel() : this.getDefaults().getMaxMergeLevel(); - } - - public int getLevelByEnchantCost(int expLevel) { - int get = this.getDefaults().getLevelByEnchantCost().getValues().entrySet().stream() - .filter(en -> expLevel >= en.getValue().intValue()).max(Comparator.comparingInt(Map.Entry::getKey)) - .map(Map.Entry::getKey).orElse(0); - - return get != 0 ? this.fineLevel(get, ObtainType.ENCHANTING) : 0; - } - - public boolean isObtainable(@NotNull ObtainType obtainType) { - if (obtainType == ObtainType.ENCHANTING && (this.isTreasure() || this.isCurse())) return false; - - return this.getObtainChance(obtainType) > 0D; - } - - public double getObtainChance(@NotNull ObtainType obtainType) { - return this.getDefaults().getObtainChance().getOrDefault(obtainType, 0D); - } - - public int getObtainLevelMin(@NotNull ObtainType obtainType) { - return this.getDefaults().getObtainLevelCap().getOrDefault(obtainType, new int[]{-1, -1})[0]; - } - - public int getObtainLevelMax(@NotNull ObtainType obtainType) { - return this.getDefaults().getObtainLevelCap().getOrDefault(obtainType, new int[]{-1, -1})[1]; - } - - public int fineLevel(int level, @NotNull ObtainType obtainType) { - int levelCapMin = this.getObtainLevelMin(obtainType); - int levelCapMax = this.getObtainLevelMax(obtainType); - - if (levelCapMin > 0 && level < levelCapMin) level = levelCapMin; - if (levelCapMax > 0 && level > levelCapMax) level = levelCapMax; - - return level; - } - - public int generateLevel() { - return Rnd.get(this.getStartLevel(), this.getMaxLevel()); - } - - public int generateLevel(@NotNull ObtainType obtainType) { - int levelCapMin = this.getObtainLevelMin(obtainType); - int levelCapMax = this.getObtainLevelMax(obtainType); - - if (levelCapMin <= 0 || levelCapMin < this.getStartLevel()) levelCapMin = this.getStartLevel(); - if (levelCapMax <= 0 || levelCapMax > this.getMaxLevel()) levelCapMax = this.getMaxLevel(); - - return Rnd.get(levelCapMin, levelCapMax); - } - - public int getAnvilMergeCost(int level) { - return (int) this.getDefaults().getAnvilMergeCost().getValue(level); - } - - /*@Override - @Deprecated - public final boolean conflictsWith(@NotNull Enchantment enchantment) { - return this.getConflicts().contains(enchantment.getKey().getKey()); - }*/ - - @Deprecated - public Enchantment getBackend() { - return EnchantUtils.getEnchantment(this.getKey()); - } - - @Override - public final boolean checkEnchantCategory(@NotNull ItemStack item) { - EnchantmentTarget category = this.getCategory(); - - if (category == EnchantmentTarget.WEAPON && ItemUtil.isAxe(item)) { - return Config.ENCHANTMENTS_ITEM_SWORD_ENCHANTS_TO_AXES.get(); - } - if (category == EnchantmentTarget.BOW && item.getType() == Material.CROSSBOW) { - return Config.ENCHANTMENTS_ITEM_BOW_ENCHANTS_TO_CROSSBOW.get(); - } - if ((category == EnchantmentTarget.ARMOR || category == EnchantmentTarget.ARMOR_TORSO) && item.getType() == Material.ELYTRA) { - return Config.ENCHANTMENTS_ITEM_CHESTPLATE_ENCHANTS_TO_ELYTRA.get(); - } - return false; - } - - @Override - public boolean checkItemCategory(@NotNull ItemStack item) { - ItemCategory[] itemCategories = this.getFitItemTypes(); - if (itemCategories.length == 0) return false; - - return Stream.of(itemCategories).anyMatch(itemCategory -> itemCategory.isIncluded(item)); - } - - @Override - public boolean isCurse() { - return false; - } - - @Override - public final boolean isTreasure() { - return this.getDefaults().isTreasure(); - } - - @Override - public boolean isTradeable() { - return this.getDefaults().isTradeable(); - } - - @Override - public boolean isDiscoverable() { - return this.getDefaults().isDiscoverable(); - } - - public boolean hasVisualEffects() { - return this.getDefaults().isVisualEffects(); - } - - public boolean isChargesEnabled() { - return Config.ENCHANTMENTS_CHARGES_ENABLED.get() && this.getDefaults().isChargesEnabled(); - } - - public boolean isChargesCustomFuel() { - return this.getDefaults().isChargesCustomFuel(); - } - - public int getChargesMax(int level) { - return this.isChargesEnabled() ? (int) this.getDefaults().getChargesMax().getValue(level) : 0; - } - - public int getChargesConsumeAmount(int level) { - return this.isChargesEnabled() ? (int) this.getDefaults().getChargesConsumeAmount().getValue(level) : 0; - } - - public int getChargesRechargeAmount(int level) { - return this.isChargesEnabled() ? (int) this.getDefaults().getChargesRechargeAmount().getValue(level) : 0; - } - - @NotNull - public ItemStack getChargesFuel() { - ItemStack fuelHas = this.getDefaults().getChargesFuel(); - if (!this.isChargesCustomFuel() || fuelHas == null || fuelHas.getType().isAir()) { - return Config.ENCHANTMENTS_CHARGES_FUEL_ITEM.get(); - } - return new ItemStack(fuelHas); - } - - public boolean isChargesFuel(@NotNull ItemStack item) { - if (Config.ENCHANTMENTS_CHARGES_COMPARE_TYPE_ONLY.get()) { - return item.getType() == this.getChargesFuel().getType(); - } - return item.isSimilar(this.getChargesFuel()); - } - - @NotNull - public NamespacedKey getChargesKey() { - return chargesKey; - } - - @Override - public boolean isOutOfCharges(@NotNull ItemStack item) { - return EnchantUtils.isOutOfCharges(item, this); - } - - @Override - public boolean isFullOfCharges(@NotNull ItemStack item) { - return EnchantUtils.isFullOfCharges(item, this); - } - - @Override - public int getCharges(@NotNull ItemStack item) { - return EnchantUtils.getCharges(item, this); - } - - @Override - public void consumeChargesNoUpdate(@NotNull ItemStack item, int level) { - if (!this.isChargesEnabled()) return; - - EnchantUtils.consumeCharges(item, this, level); - } - - @Override - public void consumeCharges(@NotNull ItemStack item, int level) { - if (!this.isChargesEnabled()) return; - - this.consumeChargesNoUpdate(item, level); - EnchantUtils.updateDisplay(item); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/AquamanEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/AquamanEnchant.java deleted file mode 100644 index 5bcb10d..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/AquamanEnchant.java +++ /dev/null @@ -1,59 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.armor; - -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class AquamanEnchant extends ExcellentEnchant implements Potioned, PassiveEnchant { - - public static final String ID = "aquaman"; - - private PotionImplementation potionImplementation; - private PeriodImplementation periodImplementation; - - public AquamanEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.4); - this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect."); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.WATER_BREATHING, true); - this.periodImplementation = PeriodImplementation.create(this, "100"); - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; - } - - @Override - @NotNull - public EnchantmentTarget getCategory() { - return EnchantmentTarget.ARMOR_HEAD; - } - - @Override - public boolean onTrigger(@NotNull LivingEntity entity, @NotNull ItemStack item, int level) { - return this.addEffect(entity, level); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ColdSteelEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ColdSteelEnchant.java index 78196eb..6876ccf 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ColdSteelEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ColdSteelEnchant.java @@ -7,51 +7,57 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class ColdSteelEnchant extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ColdSteelEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { public static final String ID = "cold_steel"; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public ColdSteelEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on attacker."); - this.getDefaults().setTier(0.3); - this.getDefaults().setLevelMax(3); + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + public ColdSteelEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on attacker."); + this.setRarity(Rarity.COMMON); + this.setMaxLevel(3); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(8, 2, 1)); - this.chanceImplementation = ChanceImplementation.create(this, - "60 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.SLOW_DIGGING, false, - "4 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.SLOW_DIGGING, false, + Modifier.add(4, 1, 1, 300), + Modifier.add(0, 1,1, 5) + ); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/DarknessCloakEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/DarknessCloakEnchant.java index d441642..e56215b 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/DarknessCloakEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/DarknessCloakEnchant.java @@ -8,51 +8,58 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class DarknessCloakEnchant extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class DarknessCloakEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { public static final String ID = "darkness_cloak"; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; - public DarknessCloakEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on attacker."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.2); + public DarknessCloakEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on attacker."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 * " + Placeholders.ENCHANTMENT_LEVEL + " * 0.75"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(11, 3, 1)); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.DARKNESS, false, - "2.5" + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.DARKNESS, false, + Modifier.add(5, 1, 1, 300), + Modifier.add(0, 1, 1, 10) + ); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ElementalProtectionEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ElementalProtectionEnchant.java index 22ecba6..0d622bc 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ElementalProtectionEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/ElementalProtectionEnchant.java @@ -7,55 +7,59 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.NumberUtil; +import java.io.File; import java.util.Set; -public class ElementalProtectionEnchant extends ExcellentEnchant implements GenericEnchant, EventListener { +import static su.nightexpress.excellentenchants.Placeholders.*; - public static final String ID = "elemental_protection"; - public static final String PLACEHOLDER_PROTECTION_AMOUNT = "%enchantment_protection_amount%"; - public static final String PLACEHOLDER_PROTECTION_CAPACITY = "%enchantment_protection_capacity%"; +public class ElementalProtectionEnchant extends AbstractEnchantmentData implements SimpeListener, GenericEnchant { + + public static final String ID = "elemental_protection"; private static final Set DAMAGE_CAUSES = Set.of( EntityDamageEvent.DamageCause.POISON, EntityDamageEvent.DamageCause.WITHER, EntityDamageEvent.DamageCause.MAGIC, EntityDamageEvent.DamageCause.FREEZE, EntityDamageEvent.DamageCause.LIGHTNING); - private EnchantScaler protectionAmount; - private double protectionCapacity; - private boolean protectionAsModifier; + private Modifier protectionAmount; + private double protectionCapacity; + private boolean protectionAsModifier; - public ElementalProtectionEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Reduces Poison, Magic, Wither, Lightning, Freeze damage by " + PLACEHOLDER_PROTECTION_AMOUNT + "."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.2); + public ElementalProtectionEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Reduces Poison, Magic, Wither, Lightning, Freeze damage by " + GENERIC_AMOUNT + "%."); + this.setMaxLevel(5); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.protectionAmount = Modifier.read(config, "Settings.Protection.Amount", + Modifier.add(0, 5, 1, 100), + "Protection amount given by enchantment."); - this.protectionAmount = EnchantScaler.read(this, "Settings.Protection.Amount", - "0.05 * " + Placeholders.ENCHANTMENT_LEVEL, - "How protection the enchantment will have?"); - this.protectionCapacity = JOption.create("Settings.Protection.Capacity", 1D, - "Maximal possible protection value from all armor pieces together.").read(cfg); - this.protectionAsModifier = JOption.create("Settings.Protection.As_Modifier", false, - "When 'true' damage will be reduced by a percent of protection value.", - "When 'false' damage will be reduced by a plain protection value.").read(cfg); + this.protectionCapacity = ConfigValue.create("Settings.Protection.Capacity", + 100D, + "Maximal possible protection value from all armor pieces together.").read(config); - this.addPlaceholder(PLACEHOLDER_PROTECTION_AMOUNT, level -> NumberUtil.format(this.getProtectionAmount(level))); - this.addPlaceholder(PLACEHOLDER_PROTECTION_CAPACITY, level -> NumberUtil.format(this.getProtectionCapacity())); + this.protectionAsModifier = ConfigValue.create("Settings.Protection.As_Modifier", + true, + "Determines if Protection value is percent based or plain amount." + ).read(config); + + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getProtectionAmount(level))); + this.addPlaceholder(GENERIC_MAX, level -> NumberUtil.format(this.getProtectionCapacity())); } @NotNull @@ -84,7 +88,7 @@ public class ElementalProtectionEnchant extends ExcellentEnchant implements Gene double protectionAmount = 0D; for (ItemStack armor : EnchantUtils.getEnchantedEquipment(entity).values()) { - int level = EnchantUtils.getLevel(armor, this.getBackend()); + int level = EnchantUtils.getLevel(armor, this.getEnchantment()); if (level <= 0) continue; protectionAmount += this.getProtectionAmount(level); @@ -96,11 +100,9 @@ public class ElementalProtectionEnchant extends ExcellentEnchant implements Gene protectionAmount = this.getProtectionCapacity(); } - if (this.isProtectionAsModifier()) { - event.setDamage(Math.max(0, event.getDamage() * (1D - protectionAmount))); - } - else { - event.setDamage(Math.max(0, event.getDamage() - protectionAmount)); - } + double damage = event.getDamage(); + double blocked = this.isProtectionAsModifier() ? damage * (1D - protectionAmount) : damage - protectionAmount; + + event.setDamage(Math.max(0, blocked)); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FireShieldEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FireShieldEnchant.java index ce909de..a090867 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FireShieldEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FireShieldEnchant.java @@ -1,54 +1,61 @@ package su.nightexpress.excellentenchants.enchantment.impl.armor; +import org.bukkit.Particle; +import org.bukkit.Sound; import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.entity.LivingEntity; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class FireShieldEnchant extends ExcellentEnchant implements Chanced, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class FireShieldEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "fire_shield"; - public static final String PLACEHOLDER_FIRE_DURATION = "%enchantment_fire_duration%"; - private EnchantScaler fireDuration; - private ChanceImplementation chanceImplementation; + private Modifier fireDuration; + private ChanceSettingsImpl chanceSettings; - public FireShieldEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to ignite the attacker for " + PLACEHOLDER_FIRE_DURATION + "s."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.4); + public FireShieldEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to ignite attackers for " + GENERIC_DURATION + "s."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3, 2, 1, 100)); - this.chanceImplementation = ChanceImplementation.create(this, - Placeholders.ENCHANTMENT_LEVEL + " * 15.0"); - this.fireDuration = EnchantScaler.read(this, "Settings.Fire.Duration", - "2.5 * " + Placeholders.ENCHANTMENT_LEVEL, + this.fireDuration = Modifier.read(config, "Settings.Fire.Duration", + Modifier.multiply(2, 1, 1, 600), "Sets the fire duration (in seconds).", "If entity's current fire ticks amount is less than this value, it will be set to this value.", "If entity's current fire ticks amount is greater than this value, it won't be changed."); - this.addPlaceholder(PLACEHOLDER_FIRE_DURATION, level -> NumberUtil.format(this.getFireDuration(level))); + this.addPlaceholder(GENERIC_DURATION, level -> NumberUtil.format(this.getFireDuration(level))); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @@ -82,6 +89,11 @@ public class FireShieldEnchant extends ExcellentEnchant implements Chanced, Comb int ticksHas = damager.getFireTicks(); if (ticksHas >= ticksToSet) return false; + if (this.hasVisualEffects()) { + UniParticle.of(Particle.FLAME).play(victim.getEyeLocation(), 0.5, 0.1, 35); + UniSound.of(Sound.ITEM_FIRECHARGE_USE).play(victim.getLocation()); + } + damager.setFireTicks(ticksToSet); return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FlameWalkerEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FlameWalkerEnchant.java index 3ba0ec1..cbf2ae1 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FlameWalkerEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/FlameWalkerEnchant.java @@ -18,69 +18,90 @@ import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.Version; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.api.server.AbstractTask; -import su.nexmedia.engine.utils.Pair; -import su.nexmedia.engine.utils.random.Rnd; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.Cleanable; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.Pair; +import su.nightexpress.nightcore.util.random.Rnd; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import java.io.File; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; -public class FlameWalkerEnchant extends ExcellentEnchant implements GenericEnchant, EventListener, Cleanable { +public class FlameWalkerEnchant extends AbstractEnchantmentData implements GenericEnchant, SimpeListener { public static final String ID = "flame_walker"; - private static final BlockFace[] FACES = {BlockFace.SOUTH, BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST}; - private static final Map> BLOCKS_TO_DESTROY = new ConcurrentHashMap<>(); + private static final BlockFace[] FACES = {BlockFace.SOUTH, BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST}; + private static final Map> BLOCKS_TO_DESTROY = new ConcurrentHashMap<>(); - private EnchantScaler blockDecayTime; - private BlockTickTask blockTickTask; + private Modifier blockDecayTime; - public FlameWalkerEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Ability to walk on lava and magma blocks without getting damage."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.7); - this.getDefaults().getConflicts().add(Enchantment.FROST_WALKER.getKey().getKey()); - - this.blockTickTask = new BlockTickTask(plugin); - this.blockTickTask.start(); + public FlameWalkerEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Ability to walk on lava, ignore magma block damage."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts(Enchantment.FROST_WALKER.getKey().getKey()); } @Override - public void loadSettings() { - super.loadSettings(); - this.blockDecayTime = EnchantScaler.read(this, "Settings.Block_Decay", "12.0", + protected void loadAdditional(@NotNull FileConfig config) { + this.blockDecayTime = Modifier.read(config, "Settings.Block_Decay", + Modifier.add(8, 1, 1, 120), "Sets up to how long (in seconds) blocks will stay before turn back to lava."); } - @Override - public void clear() { - if (this.blockTickTask != null) { - this.blockTickTask.stop(); - this.blockTickTask = null; - } - BLOCKS_TO_DESTROY.keySet().forEach(block -> block.setType(Material.LAVA)); + public static void clear() { + BLOCKS_TO_DESTROY.keySet().forEach(location -> location.getBlock().setType(Material.LAVA)); BLOCKS_TO_DESTROY.clear(); } public static void addBlock(@NotNull Block block, double seconds) { - BLOCKS_TO_DESTROY.put(block, Pair.of(System.currentTimeMillis() + (long) seconds * 1000L, Rnd.get(100))); + BLOCKS_TO_DESTROY.put(block.getLocation(), Pair.of(System.currentTimeMillis() + (long) seconds * 1000L, Rnd.get(1000))); } public static boolean isBlock(@NotNull Block block) { - return BLOCKS_TO_DESTROY.containsKey(block); + return BLOCKS_TO_DESTROY.containsKey(block.getLocation()); + } + + public static void tickBlocks() { + long now = System.currentTimeMillis(); + + BLOCKS_TO_DESTROY.keySet().removeIf(location -> location.getBlock().isLiquid() || location.getBlock().getType() != Material.MAGMA_BLOCK); + BLOCKS_TO_DESTROY.forEach((location, pair) -> { + Block block = location.getBlock(); + long time = pair.getFirst(); + if (now >= time) { + block.getWorld().getPlayers().forEach(player -> { + player.sendBlockDamage(location, 0F, pair.getSecond()); + }); + block.setType(Material.LAVA); + UniParticle.blockCrack(Material.MAGMA_BLOCK).play(location, 0.5, 0.7, 0.5, 0.03, 30); + return; + } + + long diff = TimeUnit.MILLISECONDS.toSeconds(time - now); + + float progress = (float) (1D - Math.min(1D, diff / 5D)); + if (progress > 1F) progress = 1F; + if (progress < 0F) progress = 0F; + + float finalProgress = progress; + block.getWorld().getPlayers().forEach(player -> { + player.sendBlockDamage(location, finalProgress, pair.getSecond()); + }); + }); } @Override @@ -106,16 +127,20 @@ public class FlameWalkerEnchant extends ExcellentEnchant implements GenericEncha ItemStack boots = player.getInventory().getBoots(); if (boots == null || boots.getType().isAir()) return; - int level = EnchantUtils.getLevel(boots, this.getBackend()); + int level = EnchantUtils.getLevel(boots, this.getEnchantment()); if (level <= 0) return; Block bTo = to.getBlock().getRelative(BlockFace.DOWN); boolean hasLava = Stream.of(FACES).anyMatch(face -> bTo.getRelative(face).getType() == Material.LAVA); if (!hasLava) return; - plugin.getEnchantNMS().handleFlameWalker(player, player.getLocation(), level).forEach(block -> { + Set blocks = plugin.getEnchantNMS().handleFlameWalker(player, player.getLocation(), level); + blocks.forEach(block -> { addBlock(block, Rnd.getDouble(this.getBlockDecayTime(level)) + 1); }); + if (!blocks.isEmpty()) { + this.consumeCharges(boots, level); + } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -140,7 +165,7 @@ public class FlameWalkerEnchant extends ExcellentEnchant implements GenericEncha private void processExplosion(@NotNull List blocks) { blocks.removeIf(block -> { if (isBlock(block)) { - block.setType(Material.AIR); + block.setType(Material.LAVA); return true; } return false; @@ -159,52 +184,10 @@ public class FlameWalkerEnchant extends ExcellentEnchant implements GenericEncha ItemStack boots = equipment.getBoots(); if (boots == null || boots.getType().isAir()) return; - int level = EnchantUtils.getLevel(boots, this.getBackend()); + int level = EnchantUtils.getLevel(boots, this.getEnchantment()); if (level <= 0) return; event.setCancelled(true); - } - - static class BlockTickTask extends AbstractTask { - - public BlockTickTask(@NotNull ExcellentEnchants plugin) { - super(plugin, 1, false); - } - - @Override - public void action() { - long now = System.currentTimeMillis(); - - BLOCKS_TO_DESTROY.keySet().removeIf(block -> { - if (block.isEmpty() || block.getType() != Material.MAGMA_BLOCK) return true; - - Pair pair = BLOCKS_TO_DESTROY.get(block); - long time = pair.getFirst(); - if (now >= time) { - if (Version.isAtLeast(Version.V1_19_R3)) { - block.getWorld().getPlayers().forEach(player -> { - player.sendBlockDamage(block.getLocation(), 0F, pair.getSecond()); - }); - } - - block.setType(Material.LAVA); - UniParticle.blockCrack(Material.MAGMA_BLOCK).play(block.getLocation(), 0.5, 0.7, 0.5, 0.03, 30); - return true; - } - else if (Version.isAtLeast(Version.V1_19_R3)) { - long diff = TimeUnit.MILLISECONDS.toSeconds(time - now); - - float progress = (float) (1D - Math.min(1D, diff / 5D)); - if (progress > 1F) progress = 1F; - if (progress < 0F) progress = 0F; - - float finalProgress = progress; - block.getWorld().getPlayers().forEach(player -> { - player.sendBlockDamage(block.getLocation(), finalProgress, pair.getSecond()); - }); - } - return false; - }); - } + this.consumeCharges(boots, level); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/HardenedEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/HardenedEnchant.java index 175aa06..e948fc5 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/HardenedEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/HardenedEnchant.java @@ -7,50 +7,57 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class HardenedEnchant extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class HardenedEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { public static final String ID = "hardened"; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; - public HardenedEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to obtain " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) when damaged."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.4); + public HardenedEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to get " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) when damaged."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "30.0 * " + Placeholders.ENCHANTMENT_LEVEL); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(2, 2, 1, 100)); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.DAMAGE_RESISTANCE, false, - "3.0" + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.DAMAGE_RESISTANCE, false, + Modifier.add(2, 1, 1, 300), + Modifier.add(0, 1, 1.5, 5) + ); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/IceShieldEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/IceShieldEnchant.java index 20d4435..0f0b083 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/IceShieldEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/IceShieldEnchant.java @@ -1,6 +1,8 @@ package su.nightexpress.excellentenchants.enchantment.impl.armor; import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Sound; import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.entity.LivingEntity; import org.bukkit.event.EventPriority; @@ -8,37 +10,47 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class IceShieldEnchant extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class IceShieldEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { public static final String ID = "ice_shield"; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; - public IceShieldEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to freeze and apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on attacker."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); + public IceShieldEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to freeze and apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on attacker."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "25.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.SLOW, false, - "3.0 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(4, 4, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.SLOW, false, + Modifier.add(2, 2, 1, 300), + Modifier.add(0, 1, 1, 5) + ); } @NotNull @@ -55,14 +67,14 @@ public class IceShieldEnchant extends ExcellentEnchant implements Chanced, Potio @Override @NotNull - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @Override @@ -78,8 +90,11 @@ public class IceShieldEnchant extends ExcellentEnchant implements Chanced, Potio damager.setFreezeTicks(damager.getMaxFreezeTicks()); if (this.hasVisualEffects()) { - UniParticle.blockCrack(Material.ICE).play(damager.getEyeLocation(), 0.25, 0.1, 20); + UniParticle.blockCrack(Material.ICE).play(victim.getEyeLocation(), 0.5, 0.1, 35); + UniParticle.of(Particle.CLOUD).play(victim.getEyeLocation(), 0.25, 0.1, 25); + UniSound.of(Sound.BLOCK_GLASS_BREAK).play(victim.getLocation()); } + return true; } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/JumpingEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/JumpingEnchant.java index 3520c6a..76f2819 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/JumpingEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/JumpingEnchant.java @@ -5,45 +5,51 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class JumpingEnchant extends ExcellentEnchant implements Potioned, PassiveEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class JumpingEnchant extends AbstractEnchantmentData implements PotionData, PassiveEnchant { public static final String ID = "bunny_hop"; - private PotionImplementation potionImplementation; - private PeriodImplementation periodImplementation; + private PotionSettingsImpl potionSettings; + private PeriodSettingsImpl periodSettings; - public JumpingEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect."); + public JumpingEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + this.setDescription("Grants permanent " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " effect."); } @Override - public void loadSettings() { - super.loadSettings(); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.JUMP, true); - this.periodImplementation = PeriodImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.JUMP, true); + this.periodSettings = PeriodSettingsImpl.create(config); } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @NotNull @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; + public PeriodicSettings getPeriodSettings() { + return periodSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/KamikadzeEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/KamikadzeEnchant.java index d6f9e9a..3bda942 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/KamikadzeEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/KamikadzeEnchant.java @@ -1,5 +1,6 @@ package su.nightexpress.excellentenchants.enchantment.impl.armor; +import org.bukkit.Particle; import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.entity.Entity; import org.bukkit.entity.Item; @@ -12,56 +13,59 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class KamikadzeEnchant extends ExcellentEnchant implements Chanced, DeathEnchant, EventListener { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class KamikadzeEnchant extends AbstractEnchantmentData implements ChanceData, DeathEnchant, SimpeListener { public static final String ID = "self_destruction"; - private static final String PLACEHOLDER_EXPLOSION_POWER = "%enchantment_explosion_power%"; - private EnchantScaler explosionSize; - private boolean applyOnResurrect; - private ChanceImplementation chanceImplementation; + private Modifier explosionSize; + private boolean applyOnResurrect; + private ChanceSettingsImpl chanceSettings; private Entity exploder; - public KamikadzeEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("%enchantment_trigger_chance%% chance to create an explosion on death."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); + public KamikadzeEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to create an explosion on death."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 10"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(0, 5, 1, 100)); - this.applyOnResurrect = JOption.create("Settings.Apply_On_Resurrect", true, + this.applyOnResurrect = ConfigValue.create("Settings.Apply_On_Resurrect", + true, "Sets whether or not enchantment will trigger on resurrect (when a totem is used)." - ).read(cfg); + ).read(config); - this.explosionSize = EnchantScaler.read(this, "Settings.Explosion.Size", - "1.0" + Placeholders.ENCHANTMENT_LEVEL, - "A size of the explosion. The more size - the bigger the damage."); - - this.addPlaceholder(PLACEHOLDER_EXPLOSION_POWER, level -> NumberUtil.format(this.getExplosionSize(level))); + this.explosionSize = Modifier.read(config, "Settings.Explosion.Size", + Modifier.add(1, 1, 1, 5), + "A size of the explosion. The more size - the bigger the damage." + ); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override @@ -82,9 +86,16 @@ public class KamikadzeEnchant extends ExcellentEnchant implements Chanced, Death if (!this.checkTriggerChance(level)) return false; float size = (float) this.getExplosionSize(level); + this.exploder = entity; boolean exploded = entity.getWorld().createExplosion(entity.getLocation(), size, false, false, entity); this.exploder = null; + + if (exploded && this.hasVisualEffects()) { + UniParticle.of(Particle.SMOKE_NORMAL).play(entity.getEyeLocation(), 0.5, 0.1, 60); + UniParticle.of(Particle.LAVA).play(entity.getEyeLocation(), 1.25, 0.1, 100); + } + return exploded; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/NightVisionEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/NightVisionEnchant.java index d0d3274..dd5c7d7 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/NightVisionEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/NightVisionEnchant.java @@ -5,45 +5,51 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class NightVisionEnchant extends ExcellentEnchant implements Potioned, PassiveEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class NightVisionEnchant extends AbstractEnchantmentData implements PotionData, PassiveEnchant { public static final String ID = "night_vision"; - private PotionImplementation potionImplementation; - private PeriodImplementation periodImplementation; + private PotionSettingsImpl potionSettings; + private PeriodSettingsImpl periodSettings; - public NightVisionEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.7); + public NightVisionEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Grants permanent " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " effect."); + this.setMaxLevel(1); + this.setRarity(Rarity.VERY_RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.NIGHT_VISION, true); - this.periodImplementation = PeriodImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.NIGHT_VISION, true); + this.periodSettings = PeriodSettingsImpl.create(config); } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @NotNull @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; + public PeriodicSettings getPeriodSettings() { + return periodSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/RegrowthEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/RegrowthEnchant.java index 52aed77..ca13536 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/RegrowthEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/RegrowthEnchant.java @@ -6,70 +6,79 @@ import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.EntityUtil; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.EntityUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class RegrowthEnchant extends ExcellentEnchant implements Chanced, PassiveEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class RegrowthEnchant extends AbstractEnchantmentData implements ChanceData, PassiveEnchant { public static final String ID = "regrowth"; - private static final String PLACEHOLDER_HEAL_AMOUNT = "%enchantment_heal_amount%"; - private static final String PLACEHOLDER_HEAL_MIN_HEALTH = "%enchantment_heal_min_health%"; - private static final String PLACEHOLDER_HEAL_MAX_HEALTH = "%enchantment_heal_max_health%"; + private Modifier minHealth; + private Modifier maxHealth; + private Modifier healAmount; - private EnchantScaler healMinHealth; - private EnchantScaler healMaxHealth; - private EnchantScaler healAmount; + private ChanceSettingsImpl chanceSettings; + private PeriodSettingsImpl periodSettings; - private ChanceImplementation chanceImplementation; - private PeriodImplementation periodImplementation; - - public RegrowthEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Restores " + PLACEHOLDER_HEAL_AMOUNT + " hearts every few seconds."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.7); + public RegrowthEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Restores " + GENERIC_AMOUNT + "❤ every few seconds."); + this.setMaxLevel(5); + this.setRarity(Rarity.VERY_RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(100, 0, 1, 100)); - this.periodImplementation = PeriodImplementation.create(this, "100"); + this.periodSettings = PeriodSettingsImpl.create(config); - this.healMinHealth = EnchantScaler.read(this, "Settings.Heal.Min_Health", "0.5", - "Minimal entity health for the enchantment to have effect."); - this.healMaxHealth = EnchantScaler.read(this, "Settings.Heal.Max_Health", "20.0", - "Maximal entity health when the enchantment will not heal anymore."); - this.healAmount = EnchantScaler.read(this, "Settings.Heal.Amount", "0.25", - "Amount of hearts to be restored."); + this.minHealth = Modifier.read(config, "Settings.Heal.Min_Health", + Modifier.add(0.5, 0, 0), + "Minimal entity health for the enchantment to have effect." + ); - this.addPlaceholder(PLACEHOLDER_HEAL_AMOUNT, level -> NumberUtil.format(this.getHealAmount(level))); - this.addPlaceholder(PLACEHOLDER_HEAL_MIN_HEALTH, level -> NumberUtil.format(this.getHealMaxHealth(level))); - this.addPlaceholder(PLACEHOLDER_HEAL_MAX_HEALTH, level -> NumberUtil.format(this.getHealMaxHealth(level))); + this.maxHealth = Modifier.read(config, "Settings.Heal.Max_Health", + Modifier.add(20, 0, 0), + "Maximal entity health when the enchantment will not heal anymore." + ); + + this.healAmount = Modifier.read(config, "Settings.Heal.Amount", + Modifier.add(0, 0.1, 1, 10), + "Amount of hearts to be restored." + ); + + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getHealAmount(level))); + this.addPlaceholder(GENERIC_MIN, level -> NumberUtil.format(this.getMinHealthToHeal(level))); + this.addPlaceholder(GENERIC_MAX, level -> NumberUtil.format(this.getMaxHealthToHeal(level))); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; + public PeriodicSettings getPeriodSettings() { + return periodSettings; } @NotNull @@ -82,12 +91,12 @@ public class RegrowthEnchant extends ExcellentEnchant implements Chanced, Passiv return this.healAmount.getValue(level); } - public double getHealMinHealth(int level) { - return this.healMinHealth.getValue(level); + public double getMinHealthToHeal(int level) { + return this.minHealth.getValue(level); } - public double getHealMaxHealth(int level) { - return this.healMaxHealth.getValue(level); + public double getMaxHealthToHeal(int level) { + return this.maxHealth.getValue(level); } @Override @@ -96,7 +105,7 @@ public class RegrowthEnchant extends ExcellentEnchant implements Chanced, Passiv double healthMax = EntityUtil.getAttribute(entity, Attribute.GENERIC_MAX_HEALTH); double healthHas = entity.getHealth(); - if (healthHas < this.getHealMinHealth(level) || healthHas > this.getHealMaxHealth(level)) return false; + if (healthHas < this.getMinHealthToHeal(level) || healthHas > this.getMaxHealthToHeal(level)) return false; if (healthHas >= healthMax) return false; double amount = Math.min(healthMax, healthHas + this.getHealAmount(level)); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SaturationEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SaturationEnchant.java index 79487cf..4989dd8 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SaturationEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SaturationEnchant.java @@ -5,51 +5,56 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class SaturationEnchant extends ExcellentEnchant implements PassiveEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SaturationEnchant extends AbstractEnchantmentData implements PassiveEnchant { public static final String ID = "saturation"; - private static final String PLACEHOLDER_SATURATION_AMOUNT = "%enchantment_saturation_amount%"; - private static final String PLACEHOLDER_SATURATION_MAX_FOOD_LEVEL = "%enchantment_saturation_max_food_level%"; + private Modifier feedAmount; + private Modifier maxFoodLevel; - private EnchantScaler saturationAmount; - private EnchantScaler saturationMaxFoodLevel; + private PeriodSettingsImpl periodSettings; - private PeriodImplementation periodImplementation; - - public SaturationEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Restores " + PLACEHOLDER_SATURATION_AMOUNT + " food points every few seconds."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); + public SaturationEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Restores " + GENERIC_AMOUNT + " food points every few seconds."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.periodImplementation = PeriodImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.periodSettings = PeriodSettingsImpl.create(config); - this.saturationAmount = EnchantScaler.read(this, "Settings.Saturation.Amount", Placeholders.ENCHANTMENT_LEVEL, + this.feedAmount = Modifier.read(config, "Settings.Saturation.Amount", + Modifier.add(0, 1, 1, 10), "Amount of food points to restore."); - this.saturationMaxFoodLevel = EnchantScaler.read(this, "Settings.Saturation.Max_Food_Level", "20", + + this.maxFoodLevel = Modifier.read(config, "Settings.Saturation.Max_Food_Level", + Modifier.add(20, 0, 0), "Maximal player's food level for the enchantment to stop feeding them."); - this.addPlaceholder(PLACEHOLDER_SATURATION_AMOUNT, level -> NumberUtil.format(this.getSaturationAmount(level))); - this.addPlaceholder(PLACEHOLDER_SATURATION_MAX_FOOD_LEVEL, level -> NumberUtil.format(this.getMaxFoodLevel(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getFeedAmount(level))); + this.addPlaceholder(GENERIC_MAX, level -> NumberUtil.format(this.getMaxFoodLevel(level))); } @NotNull @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; + public PeriodicSettings getPeriodSettings() { + return periodSettings; } @Override @@ -58,12 +63,12 @@ public class SaturationEnchant extends ExcellentEnchant implements PassiveEnchan return EnchantmentTarget.ARMOR_HEAD; } - public final int getSaturationAmount(int level) { - return (int) this.saturationAmount.getValue(level); + public final int getFeedAmount(int level) { + return (int) this.feedAmount.getValue(level); } public final int getMaxFoodLevel(int level) { - return (int) this.saturationMaxFoodLevel.getValue(level); + return (int) this.maxFoodLevel.getValue(level); } @Override @@ -71,7 +76,7 @@ public class SaturationEnchant extends ExcellentEnchant implements PassiveEnchan if (!(entity instanceof Player player)) return false; if (player.getFoodLevel() >= this.getMaxFoodLevel(level)) return false; - int amount = this.getSaturationAmount(level); + int amount = this.getFeedAmount(level); player.setFoodLevel(Math.min(20, player.getFoodLevel() + amount)); return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SpeedyEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SpeedyEnchant.java index 0cce14d..4e7ba76 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SpeedyEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/SpeedyEnchant.java @@ -5,45 +5,51 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class SpeedyEnchant extends ExcellentEnchant implements Potioned, PassiveEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SpeedyEnchant extends AbstractEnchantmentData implements PotionData, PassiveEnchant { public static final String ID = "sonic"; - private PotionImplementation potionImplementation; - private PeriodImplementation periodImplementation; + private PotionSettingsImpl potionSettings; + private PeriodSettingsImpl periodSettings; - public SpeedyEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); + public SpeedyEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Grants permanent " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " effect."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.SPEED, true); - this.periodImplementation = PeriodImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.SPEED, true); + this.periodSettings = PeriodSettingsImpl.create(config); } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @NotNull @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; + public PeriodicSettings getPeriodSettings() { + return periodSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/StoppingForceEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/StoppingForceEnchant.java index 59f90cc..15edd16 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/StoppingForceEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/StoppingForceEnchant.java @@ -6,40 +6,44 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class StoppingForceEnchant extends ExcellentEnchant implements Chanced, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class StoppingForceEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "stopping_force"; - public static final String PLACEHOLDER_KNOCKBACK_RESISTANCE = "%knockback_resistance%"; + private ChanceSettingsImpl chanceSettings; + private Modifier knockbackModifier; - private ChanceImplementation chanceImplementation; - private EnchantScaler knockbackModifier; - - public StoppingForceEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to resist knockback in combat by " + PLACEHOLDER_KNOCKBACK_RESISTANCE + "%."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); + public StoppingForceEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to resist knockback in combat by " + GENERIC_AMOUNT + "%."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100.0"); - this.knockbackModifier = EnchantScaler.read(this, "Settings.Knockback_Modifier", - "0.7 - " + Placeholders.ENCHANTMENT_LEVEL + " / 5.0", + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(100, 0, 0, 100)); + + this.knockbackModifier = Modifier.read(config, "Settings.Knockback_Modifier", + Modifier.add(0.9, -0.2, 1), "Sets the knockback multiplier when taking damage.", "Lower value = less knockback."); - this.addPlaceholder(PLACEHOLDER_KNOCKBACK_RESISTANCE, level -> NumberUtil.format(this.getKnockbackModifier(level) * 100)); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getKnockbackModifier(level) * 100)); } public double getKnockbackModifier(int level) { @@ -60,8 +64,8 @@ public class StoppingForceEnchant extends ExcellentEnchant implements Chanced, C @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } @Override @@ -73,8 +77,10 @@ public class StoppingForceEnchant extends ExcellentEnchant implements Chanced, C public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { if (!this.checkTriggerChance(level)) return false; + double mod = Math.max(0, this.getKnockbackModifier(level)); + this.plugin.runTask(task -> { - victim.setVelocity(victim.getVelocity().multiply(this.getKnockbackModifier(level))); + victim.setVelocity(victim.getVelocity().multiply(mod)); }); return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/TreasureHunterEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/TreasureHunterEnchant.java new file mode 100644 index 0000000..f27f300 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/TreasureHunterEnchant.java @@ -0,0 +1,121 @@ +package su.nightexpress.excellentenchants.enchantment.impl.armor; + +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.LootGenerateEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.loot.LootTable; +import org.bukkit.loot.LootTables; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.random.Rnd; + +import java.io.File; +import java.util.*; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class TreasureHunterEnchant extends AbstractEnchantmentData implements ChanceData, GenericEnchant, SimpeListener { + + public static final String ID = "treasure_hunter"; + + private ChanceSettingsImpl chanceSettings; + + private final Set lootTables; + + public TreasureHunterEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to get more items in loot chests."); + this.setMaxLevel(4); + this.setRarity(Rarity.RARE); + + this.lootTables = new HashSet<>(); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(2.5, 2.5, 1, 100)); + + boolean isWhitelist = ConfigValue.create("Settings.LootTables.Whitelist", + false, + "When 'true', uses only loot tables listed below.", + "When 'false', uses ALL loot tables except ones listed below.", + "[Default is false]" + ).read(config); + + Set tables = ConfigValue.forSet("Settings.LootTables.List", + id -> StringUtil.getEnum(id, LootTables.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of( + LootTables.ENDER_DRAGON, + LootTables.END_CITY_TREASURE + ), + "List of loot tables that are added or excluded (depends on Whitelist setting) for this enchantment.", + "Available loot table names: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/loot/LootTables.html" + ).read(config); + + if (isWhitelist) { + this.lootTables.addAll(tables); + } + else { + this.lootTables.addAll(Arrays.asList(LootTables.values())); + this.lootTables.removeAll(tables); + } + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @Override + @NotNull + public EnchantmentTarget getCategory() { + return EnchantmentTarget.ARMOR_HEAD; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onLootExplore(LootGenerateEvent event) { + if (this.lootTables.isEmpty()) return; + + if (!(event.getEntity() instanceof Player player)) return; + if (!this.isAvailableToUse(player)) return; + + ItemStack helmet = player.getInventory().getHelmet(); + if (helmet == null || helmet.getType().isAir()) return; + + int level = EnchantUtils.getLevel(helmet, this.getEnchantment()); + if (level < 1) return; + + if (!this.checkTriggerChance(level)) return; + + InventoryHolder holder = event.getInventoryHolder(); + if (holder == null) return; + + Inventory inventory = holder.getInventory(); + + LootTable lootTable = Rnd.get(this.lootTables).getLootTable(); + + Collection items = lootTable.populateLoot(Rnd.RANDOM, event.getLootContext()); + items.forEach(inventory::addItem); + + this.consumeCharges(helmet, level); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/WaterBreathingEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/WaterBreathingEnchant.java new file mode 100644 index 0000000..d1f95ea --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/armor/WaterBreathingEnchant.java @@ -0,0 +1,65 @@ +package su.nightexpress.excellentenchants.enchantment.impl.armor; + +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class WaterBreathingEnchant extends AbstractEnchantmentData implements PotionData, PassiveEnchant { + + public static final String ID = "aquaman"; + + private PotionSettingsImpl potionSettings; + private PeriodSettingsImpl periodSettings; + + public WaterBreathingEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setMaxLevel(1); + this.setRarity(Rarity.UNCOMMON); + this.setDescription("Grants permanent " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " effect."); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.WATER_BREATHING, true); + this.periodSettings = PeriodSettingsImpl.create(config); + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public PeriodicSettings getPeriodSettings() { + return periodSettings; + } + + @Override + @NotNull + public EnchantmentTarget getCategory() { + return EnchantmentTarget.ARMOR_HEAD; + } + + @Override + public boolean onTrigger(@NotNull LivingEntity entity, @NotNull ItemStack item, int level) { + return this.addEffect(entity, level); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantBomber.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/BomberEnchant.java similarity index 53% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantBomber.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/BomberEnchant.java index 0626cb7..05d3b36 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantBomber.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/BomberEnchant.java @@ -11,34 +11,39 @@ import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class EnchantBomber extends ExcellentEnchant implements Chanced, BowEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class BomberEnchant extends AbstractEnchantmentData implements ChanceData, BowEnchant { public static final String ID = "bomber"; - public static final String PLACEHOLDER_FUSE_TICKS = "%enchantment_fuse_ticks%"; - private EnchantScaler fuseTicks; - private ChanceImplementation chanceImplementation; + private Modifier fuseTicks; + private ChanceSettingsImpl chanceSettings; - public EnchantBomber(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch TNT that explodes in " + PLACEHOLDER_FUSE_TICKS + "s."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.7); - this.getDefaults().setConflicts( - EnchantEnderBow.ID, EnchantGhast.ID, - EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID, - EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID, + public BomberEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch TNT that explodes in " + GENERIC_TIME + "s."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts( + EnderBowEnchant.ID, GhastEnchant.ID, + ExplosiveArrowsEnchant.ID, PoisonedArrowsEnchant.ID, ConfusingArrowsEnchant.ID, + WitheredArrowsEnchant.ID, ElectrifiedArrowsEnchant.ID, DragonfireArrowsEnchant.ID, DarknessArrowsEnchant.ID, - EnchantHover.ID, FlareEnchant.ID, + HoverEnchant.ID, FlareEnchant.ID, Enchantment.ARROW_FIRE.getKey().getKey(), Enchantment.ARROW_KNOCKBACK.getKey().getKey(), Enchantment.ARROW_DAMAGE.getKey().getKey() @@ -46,21 +51,20 @@ public class EnchantBomber extends ExcellentEnchant implements Chanced, BowEncha } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "5.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.fuseTicks = EnchantScaler.read(this, "Settings.Fuse_Ticks", - "100 - " + Placeholders.ENCHANTMENT_LEVEL + " * 10", + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3.5, 1.5, 1, 100)); + + this.fuseTicks = Modifier.read(config, "Settings.Fuse_Ticks", + Modifier.add(110, -10, 1), "Sets fuse ticks (before it will explode) for the launched TNT."); - this.addPlaceholder(PLACEHOLDER_FUSE_TICKS, level -> NumberUtil.format((double) this.getFuseTicks(level) / 20D)); + this.addPlaceholder(GENERIC_TIME, level -> NumberUtil.format((double) this.getFuseTicks(level) / 20D)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public int getFuseTicks(int level) { @@ -84,9 +88,11 @@ public class EnchantBomber extends ExcellentEnchant implements Chanced, BowEncha if (!this.checkTriggerChance(level)) return false; if (!(event.getProjectile() instanceof Projectile projectile)) return false; + int fuseTicks = Math.max(1, this.getFuseTicks(level)); + TNTPrimed primed = projectile.getWorld().spawn(projectile.getLocation(), TNTPrimed.class); primed.setVelocity(projectile.getVelocity().multiply(event.getForce() * 1.25)); - primed.setFuseTicks(this.getFuseTicks(level)); + primed.setFuseTicks(fuseTicks); primed.setSource(shooter); event.setProjectile(primed); return true; diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ConfusingArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ConfusingArrowsEnchant.java new file mode 100644 index 0000000..43a132b --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ConfusingArrowsEnchant.java @@ -0,0 +1,101 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.AbstractArrow; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.*; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ConfusingArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, PotionData, BowEnchant { + + public static final String ID = "confusing_arrows"; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public ConfusingArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.)"); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.SPELL_MOB)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(10, 5, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.CONFUSION, false, + Modifier.add(3, 3, 1, 300), + Modifier.add(0, 1, 1, 10) + ); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + if (!(event.getProjectile() instanceof Arrow arrow)) return false; + if (!this.checkTriggerChance(level)) return false; + + arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); + return arrow.addCustomEffect(this.createEffect(level), true); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DarknessArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DarknessArrowsEnchant.java index 3b630f3..e2a360a 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DarknessArrowsEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DarknessArrowsEnchant.java @@ -12,61 +12,66 @@ import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.*; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class DarknessArrowsEnchant extends ExcellentEnchant implements Chanced, Arrowed, Potioned, BowEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class DarknessArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, PotionData, BowEnchant { public static final String ID = "darkness_arrows"; - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; - public DarknessArrowsEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.)"); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); + public DarknessArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.)"); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); } @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.ASH)); - this.chanceImplementation = ChanceImplementation.create(this, - "25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5.0"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.DARKNESS, false, - "4.0 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.ASH)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(8, 4, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.DARKNESS, false, + Modifier.add(3.5, 1.5, 1, 300), + Modifier.add(0, 1, 1, 5) + ); } @NotNull @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; + public ArrowSettings getArrowSettings() { + return arrowSettings; } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @NotNull @@ -81,6 +86,7 @@ public class DarknessArrowsEnchant extends ExcellentEnchant implements Chanced, if (!this.checkTriggerChance(level)) return false; arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); + return arrow.addCustomEffect(this.createEffect(level), true); } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DragonfireArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DragonfireArrowsEnchant.java new file mode 100644 index 0000000..0dadc83 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/DragonfireArrowsEnchant.java @@ -0,0 +1,168 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.*; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.LingeringPotionSplashEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.projectiles.ProjectileSource; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowData; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.ItemUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.Version; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class DragonfireArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, BowEnchant { + + public static final String ID = "dragonfire_arrows"; + + private Modifier fireDuration; + private Modifier fireRadius; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + + public DragonfireArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an dragonfire arrow (R=" + GENERIC_RADIUS + ", " + GENERIC_DURATION + "s)."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.DRAGON_BREATH)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3, 3, 1, 100)); + + this.fireDuration = Modifier.read(config, "Settings.Fire.Duration", + Modifier.multiply(100, 1, 1, 60 * 20), + "Sets the dragonfire cloud effect duration (in ticks). 20 ticks = 1 second."); + + this.fireRadius = Modifier.read(config, "Settings.Fire.Radius", + Modifier.add(1, 1, 1, 5), + "Sets the dragonfire cloud effect radius."); + + this.addPlaceholder(GENERIC_DURATION, level -> NumberUtil.format(this.getFireDuration(level) / 20D)); + this.addPlaceholder(GENERIC_RADIUS, level -> NumberUtil.format(this.getFireRadius(level))); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + public int getFireDuration(int level) { + return (int) this.fireDuration.getValue(level); + } + + public double getFireRadius(int level) { + return this.fireRadius.getValue(level); + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + return this.checkTriggerChance(level); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + if (event.getHitEntity() != null) return false; + if (projectile.getShooter() == null) return false; + + this.createCloud(projectile.getShooter(), projectile.getLocation(), event.getHitEntity(), event.getHitBlock(), event.getHitBlockFace(), level); + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + this.createCloud(shooter, victim.getLocation(), victim, null, null, level); + return false; + } + + private void createCloud(@NotNull ProjectileSource shooter, @NotNull Location location, + @Nullable Entity hitEntity, @Nullable Block hitBlock, @Nullable BlockFace hitFace, + int level) { + World world = location.getWorld(); + if (world == null) return; + + // There are some tweaks to respect protection plugins by using event call. + + ItemStack item = new ItemStack(Material.LINGERING_POTION); + ItemUtil.editMeta(item, meta -> { + if (meta instanceof PotionMeta potionMeta) { + potionMeta.addCustomEffect(new PotionEffect(PotionEffectType.HARM, 20, 0), true); + } + }); + + ThrownPotion potion = shooter.launchProjectile(ThrownPotion.class); + potion.setItem(item); + potion.teleport(location); + + AreaEffectCloud cloud = world.spawn(location, AreaEffectCloud.class); + cloud.clearCustomEffects(); + cloud.setSource(shooter); + cloud.setParticle(Particle.DRAGON_BREATH); + cloud.setRadius((float) this.getFireRadius(level)); + cloud.setDuration(this.getFireDuration(level)); + cloud.setRadiusPerTick((7.0F - cloud.getRadius()) / (float) cloud.getDuration()); + cloud.addCustomEffect(new PotionEffect(PotionEffectType.HARM, 1, 1), true); + + LingeringPotionSplashEvent splashEvent; + + if (Version.isAtLeast(Version.V1_20_R3)) { + splashEvent = new LingeringPotionSplashEvent(potion, hitEntity, hitBlock, hitFace, cloud); + } + else { + splashEvent = new LingeringPotionSplashEvent(potion, cloud); + } + + plugin.getPluginManager().callEvent(splashEvent); + if (splashEvent.isCancelled()) { + cloud.remove(); + } + potion.remove(); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ElectrifiedArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ElectrifiedArrowsEnchant.java new file mode 100644 index 0000000..17164b2 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ElectrifiedArrowsEnchant.java @@ -0,0 +1,130 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowData; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.LocationUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.ENCHANTMENT_CHANCE; +import static su.nightexpress.excellentenchants.Placeholders.GENERIC_DAMAGE; + +public class ElectrifiedArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, BowEnchant { + + public static final String ID = "electrified_arrows"; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private Modifier damageModifier; + private boolean thunderstormOnly; + + public ElectrifiedArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance for an arrow to strike lightning with " + GENERIC_DAMAGE + "❤ extra damage."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.FIREWORKS_SPARK)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(0, 5, 1, 100)); + + this.thunderstormOnly = ConfigValue.create("Settings.During_Thunderstorm_Only", + false, + "Sets whether or not enchantment will have effect only during thunderstorm in the world." + ).read(config); + + this.damageModifier = Modifier.read(config, "Settings.Damage_Modifier", + Modifier.add(1.25, 0.25, 1, 10000), + "Sets additional damage caused by enchantment's effect." + ); + + this.addPlaceholder(GENERIC_DAMAGE, level -> NumberUtil.format(this.getDamage(level))); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + public boolean isDuringThunderstormOnly() { + return thunderstormOnly; + } + + public double getDamage(int level) { + return this.damageModifier.getValue(level); + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + private void summonLightning(@NotNull Block block) { + Location location = block.getLocation(); + block.getWorld().strikeLightningEffect(location); + + if (this.hasVisualEffects()) { + Location center = LocationUtil.getCenter(location.add(0, 1, 0), false); + UniParticle.blockCrack(block.getType()).play(center, 0.5, 0.1, 100); + UniParticle.of(Particle.FIREWORKS_SPARK).play(center, 0.75, 0.05, 120); + } + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + return this.checkTriggerChance(level); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + if (event.getHitEntity() != null || event.getHitBlock() == null) return false; + + Block block = event.getHitBlock(); + this.summonLightning(block); + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + this.summonLightning(victim.getLocation().getBlock().getRelative(BlockFace.DOWN)); + event.setDamage(event.getDamage() + this.getDamage(level)); + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantConfusingArrows.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantConfusingArrows.java deleted file mode 100644 index a6eed53..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantConfusingArrows.java +++ /dev/null @@ -1,96 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.AbstractArrow; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantConfusingArrows extends ExcellentEnchant implements Chanced, Arrowed, Potioned, BowEnchant { - - public static final String ID = "confusing_arrows"; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantConfusingArrows(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.)"); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.SPELL_MOB)); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5.0"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.CONFUSION, false, - "6.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 3.0", - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - if (!(event.getProjectile() instanceof Arrow arrow)) return false; - if (!this.checkTriggerChance(level)) return false; - - arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); - return arrow.addCustomEffect(this.createEffect(level), true); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantDragonfireArrows.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantDragonfireArrows.java deleted file mode 100644 index 9d7ecfb..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantDragonfireArrows.java +++ /dev/null @@ -1,155 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.World; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.AreaEffectCloud; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.entity.ThrownPotion; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.LingeringPotionSplashEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.projectiles.ProjectileSource; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.ItemUtil; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; - -public class EnchantDragonfireArrows extends ExcellentEnchant implements Chanced, Arrowed, BowEnchant { - - public static final String ID = "dragonfire_arrows"; - - public static final String PLACEHOLDER_FIRE_RADIUS = "%enchantment_fire_radius%"; - public static final String PLACEHOLDER_FIRE_DURATION = "%enchantment_fire_duration%"; - - private EnchantScaler fireDuration; - private EnchantScaler fireRadius; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - - public EnchantDragonfireArrows(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an dragonfire arrow (R=" + PLACEHOLDER_FIRE_RADIUS + ", " + PLACEHOLDER_FIRE_DURATION + "s)."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.7); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.DRAGON_BREATH)); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - this.fireDuration = EnchantScaler.read(this, "Settings.Fire.Duration", - "100 * " + Placeholders.ENCHANTMENT_LEVEL, - "Sets the dragonfire cloud effect duration (in ticks). 20 ticks = 1 second."); - this.fireRadius = EnchantScaler.read(this, "Settings.Fire.Radius", - "2.0 + " + Placeholders.ENCHANTMENT_LEVEL, - "Sets the dragonfire cloud effect radius."); - - this.addPlaceholder(PLACEHOLDER_FIRE_DURATION, level -> NumberUtil.format(this.getFireDuration(level) / 20D)); - this.addPlaceholder(PLACEHOLDER_FIRE_RADIUS, level -> NumberUtil.format(this.getFireRadius(level))); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - public int getFireDuration(int level) { - return (int) this.fireDuration.getValue(level); - } - - public double getFireRadius(int level) { - return this.fireRadius.getValue(level); - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - return this.checkTriggerChance(level); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - if (!this.isOurProjectile(projectile)) return false; - if (event.getHitEntity() != null) return false; - if (projectile.getShooter() == null) return false; - - this.createCloud(projectile.getShooter(), projectile.getLocation() , level); - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.isOurProjectile(projectile)) return false; - - this.createCloud(shooter, victim.getLocation(), level); - return false; - } - - private void createCloud(@NotNull ProjectileSource shooter, @NotNull Location location, int level) { - World world = location.getWorld(); - if (world == null) return; - - // There are some tweaks to respect protection plugins using even call. - - ItemStack item = new ItemStack(Material.LINGERING_POTION); - ItemUtil.mapMeta(item, meta -> { - if (meta instanceof PotionMeta potionMeta) { - potionMeta.addCustomEffect(new PotionEffect(PotionEffectType.HARM, 20, 0), true); - } - }); - - ThrownPotion potion = shooter.launchProjectile(ThrownPotion.class); - potion.setItem(item); - potion.teleport(location); - - AreaEffectCloud cloud = world.spawn(location, AreaEffectCloud.class); - cloud.clearCustomEffects(); - cloud.setSource(shooter); - cloud.setParticle(Particle.DRAGON_BREATH); - cloud.setRadius((float) this.getFireRadius(level)); - cloud.setDuration(this.getFireDuration(level)); - cloud.setRadiusPerTick((7.0F - cloud.getRadius()) / (float) cloud.getDuration()); - cloud.addCustomEffect(new PotionEffect(PotionEffectType.HARM, 1, 1), true); - - LingeringPotionSplashEvent splashEvent = new LingeringPotionSplashEvent(potion, cloud); - plugin.getPluginManager().callEvent(splashEvent); - if (splashEvent.isCancelled()) { - cloud.remove(); - } - potion.remove(); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantElectrifiedArrows.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantElectrifiedArrows.java deleted file mode 100644 index 5d9ed27..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantElectrifiedArrows.java +++ /dev/null @@ -1,114 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.block.Block; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.Item; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.metadata.FixedMetadataValue; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.LocationUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; - -public class EnchantElectrifiedArrows extends ExcellentEnchant implements Chanced, Arrowed, BowEnchant { - - public static final String ID = "electrified_arrows"; - - private static final String META_NO_ITEM_DAMAGE = "itemNoDamage"; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - - public EnchantElectrifiedArrows(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an electrified arrow."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.FIREWORKS_SPARK)); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - return this.checkTriggerChance(level); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - if (!this.isOurProjectile(projectile)) return false; - if (event.getHitEntity() != null || event.getHitBlock() == null) return false; - - Block block = event.getHitBlock(); - block.getWorld().strikeLightning(block.getLocation()).setMetadata(META_NO_ITEM_DAMAGE, new FixedMetadataValue(plugin, true)); - if (this.hasVisualEffects()) { - Location center = LocationUtil.getCenter(block.getLocation()); - UniParticle.blockCrack(block.getType()).play(center, 1, 0.05, 120); - UniParticle.of(Particle.FIREWORKS_SPARK).play(center, 1, 0.05, 120); - } - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.isOurProjectile(projectile)) return false; - - plugin.getServer().getScheduler().runTask(plugin, () -> { - if (victim.isDead()) return; - victim.setNoDamageTicks(0); - victim.getWorld().strikeLightning(victim.getLocation()).setMetadata(META_NO_ITEM_DAMAGE, new FixedMetadataValue(plugin, true)); - }); - - return false; - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onItemDamage(EntityDamageByEntityEvent e) { - if (!e.getDamager().hasMetadata(META_NO_ITEM_DAMAGE)) return; - if (e.getEntity() instanceof Item || e.getEntity() instanceof ItemFrame) { - e.setCancelled(true); - e.getEntity().setFireTicks(0); - } - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantExplosiveArrows.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantExplosiveArrows.java deleted file mode 100644 index 4296cb6..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantExplosiveArrows.java +++ /dev/null @@ -1,137 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Particle; -import org.bukkit.World; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.*; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; - -public class EnchantExplosiveArrows extends ExcellentEnchant implements Chanced, Arrowed, BowEnchant { - - public static final String ID = "explosive_arrows"; - public static final String PLACEHOLDER_EXPLOSION_POWER = "%enchantment_explosion_power%"; - - private boolean explosionFireSpread; - private boolean explosionDamageItems; - private boolean explosionDamageBlocks; - private EnchantScaler explosionSize; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - - private Entity lastExploder; - - public EnchantExplosiveArrows(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an explosive arrow."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.7); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.SMOKE_NORMAL)); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - this.explosionFireSpread = JOption.create("Settings.Explosion.Fire_Spread", true, - "When 'true' creates fire on nearby blocks.").read(cfg); - this.explosionDamageItems = JOption.create("Settings.Explosion.Damage_Items", false, - "When 'true' inflicts damage to items on the ground.").read(cfg); - this.explosionDamageBlocks = JOption.create("Settings.Explosion.Damage_Blocks", false, - "When 'true' allows to break blocks by explosion.").read(cfg); - this.explosionSize = EnchantScaler.read(this, "Settings.Explosion.Size", - "2.0 + " + Placeholders.ENCHANTMENT_LEVEL, - "Sets the explosion size. The more size - the bigger explosion."); - - this.addPlaceholder(PLACEHOLDER_EXPLOSION_POWER, level -> NumberUtil.format(this.getExplosionSize(level))); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - public final double getExplosionSize(int level) { - return this.explosionSize.getValue(level); - } - - public final boolean isExplosionFireSpread() { - return this.explosionFireSpread; - } - - public final boolean isExplosionDamageBlocks() { - return this.explosionDamageBlocks; - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - return this.checkTriggerChance(level); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - if (!this.isOurProjectile(projectile)) return false; - - if (projectile.getShooter() instanceof Entity entity) { - this.lastExploder = entity; - } - - World world = projectile.getWorld(); - float explSize = (float) this.getExplosionSize(level); - boolean explFire = this.isExplosionFireSpread(); - boolean explBlocks = this.isExplosionDamageBlocks(); - boolean exploded = world.createExplosion(projectile.getLocation(), explSize, explFire, explBlocks, this.lastExploder); - this.lastExploder = null; - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onItemDamage(EntityDamageByEntityEvent event) { - if (event.getCause() != EntityDamageEvent.DamageCause.ENTITY_EXPLOSION) return; - if (this.explosionDamageItems) return; - if (this.lastExploder == null || this.lastExploder != event.getDamager()) return; - - if (event.getEntity() instanceof Item || event.getEntity() instanceof ItemFrame) { - event.setCancelled(true); - } - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantHover.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantHover.java deleted file mode 100644 index 841b7e2..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantHover.java +++ /dev/null @@ -1,96 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.AbstractArrow; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantHover extends ExcellentEnchant implements Chanced, Arrowed, Potioned, BowEnchant { - - public static final String ID = "hover"; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantHover(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.)"); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.BUBBLE_POP)); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.LEVITATION, false, - "2.5 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - if (!(event.getProjectile() instanceof Arrow arrow)) return false; - if (!this.checkTriggerChance(level)) return false; - - arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); - return arrow.addCustomEffect(this.createEffect(level), true); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantPoisonedArrows.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantPoisonedArrows.java deleted file mode 100644 index 5f26d3b..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantPoisonedArrows.java +++ /dev/null @@ -1,96 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.AbstractArrow; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantPoisonedArrows extends ExcellentEnchant implements Chanced, Arrowed, Potioned, BowEnchant { - - public static final String ID = "poisoned_arrows"; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantPoisonedArrows(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.)"); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.SLIME)); - this.chanceImplementation = ChanceImplementation.create(this, - "25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.POISON, false, - "2.5 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - if (!(event.getProjectile() instanceof Arrow arrow)) return false; - if (!this.checkTriggerChance(level)) return false; - - arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); - return arrow.addCustomEffect(this.createEffect(level), true); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantWitheredArrows.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantWitheredArrows.java deleted file mode 100644 index 028581f..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantWitheredArrows.java +++ /dev/null @@ -1,96 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.bow; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.AbstractArrow; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantWitheredArrows extends ExcellentEnchant implements Chanced, Arrowed, Potioned, BowEnchant { - - public static final String ID = "withered_arrows"; - - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantWitheredArrows(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.)"); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.SPELL_WITCH)); - this.chanceImplementation = ChanceImplementation.create(this, - "15.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5.0"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.WITHER, false, - "2.5 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.75", - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ArrowImplementation getArrowImplementation() { - return arrowImplementation; - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.BOW; - } - - @Override - public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - if (!(event.getProjectile() instanceof Arrow arrow)) return false; - if (!this.checkTriggerChance(level)) return false; - - arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); - return arrow.addCustomEffect(this.createEffect(level), true); - } - - @Override - public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - return false; - } - - @Override - public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantEnderBow.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnderBowEnchant.java similarity index 59% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantEnderBow.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnderBowEnchant.java index 0db56b4..182bd3b 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantEnderBow.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnderBowEnchant.java @@ -11,30 +11,35 @@ import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class EnchantEnderBow extends ExcellentEnchant implements BowEnchant, Chanced { +import java.io.File; + +public class EnderBowEnchant extends AbstractEnchantmentData implements ChanceData, BowEnchant { public static final String ID = "ender_bow"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public EnchantEnderBow(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Shoots ender pearls instead of arrows."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(1.0); + public EnderBowEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Shoots ender pearls instead of arrows."); + this.setMaxLevel(1); + this.setRarity(Rarity.VERY_RARE); - this.getDefaults().setConflicts( - EnchantBomber.ID, EnchantGhast.ID, - EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID, - EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID, + this.setConflicts( + BomberEnchant.ID, GhastEnchant.ID, + ExplosiveArrowsEnchant.ID, PoisonedArrowsEnchant.ID, ConfusingArrowsEnchant.ID, + WitheredArrowsEnchant.ID, ElectrifiedArrowsEnchant.ID, DragonfireArrowsEnchant.ID, DarknessArrowsEnchant.ID, VampiricArrowsEnchant.ID, - EnchantHover.ID, FlareEnchant.ID, + HoverEnchant.ID, FlareEnchant.ID, Enchantment.ARROW_FIRE.getKey().getKey(), Enchantment.ARROW_KNOCKBACK.getKey().getKey(), Enchantment.ARROW_DAMAGE.getKey().getKey() @@ -42,15 +47,14 @@ public class EnchantEnderBow extends ExcellentEnchant implements BowEnchant, Cha } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ExplosiveArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ExplosiveArrowsEnchant.java new file mode 100644 index 0000000..4c3fee2 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/ExplosiveArrowsEnchant.java @@ -0,0 +1,148 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Particle; +import org.bukkit.World; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowData; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ExplosiveArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, BowEnchant, SimpeListener { + + public static final String ID = "explosive_arrows"; + + private boolean explosionFireSpread; + private boolean explosionDamageItems; + private boolean explosionDamageBlocks; + private Modifier explosionSize; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + + private Entity lastExploder; + + public ExplosiveArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an explosive arrow."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.SMOKE_NORMAL)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3, 2, 1, 100)); + + this.explosionFireSpread = ConfigValue.create("Settings.Explosion.Fire_Spread", + true, + "When 'true' creates fire on nearby blocks.").read(config); + + this.explosionDamageItems = ConfigValue.create("Settings.Explosion.Damage_Items", + false, + "When 'true' inflicts damage to items on the ground.").read(config); + + this.explosionDamageBlocks = ConfigValue.create("Settings.Explosion.Damage_Blocks", + false, + "When 'true' allows to break blocks by explosion.").read(config); + + this.explosionSize = Modifier.read(config, "Settings.Explosion.Size", + Modifier.add(1, 1, 1, 5), + "Sets the explosion size. The more size - the bigger explosion."); + + this.addPlaceholder(GENERIC_RADIUS, level -> NumberUtil.format(this.getExplosionSize(level))); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + public final double getExplosionSize(int level) { + return this.explosionSize.getValue(level); + } + + public final boolean isExplosionFireSpread() { + return this.explosionFireSpread; + } + + public final boolean isExplosionDamageBlocks() { + return this.explosionDamageBlocks; + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + return this.checkTriggerChance(level); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + if (projectile.getShooter() instanceof Entity entity) { + this.lastExploder = entity; + } + + World world = projectile.getWorld(); + float explSize = (float) this.getExplosionSize(level); + boolean explFire = this.isExplosionFireSpread(); + boolean explBlocks = this.isExplosionDamageBlocks(); + /*boolean exploded = */world.createExplosion(projectile.getLocation(), explSize, explFire, explBlocks, this.lastExploder); + this.lastExploder = null; + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onItemDamage(EntityDamageByEntityEvent event) { + if (event.getCause() != EntityDamageEvent.DamageCause.ENTITY_EXPLOSION) return; + if (this.explosionDamageItems) return; + if (this.lastExploder == null || this.lastExploder != event.getDamager()) return; + + if (event.getEntity() instanceof Item || event.getEntity() instanceof ItemFrame) { + event.setCancelled(true); + } + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/FlareEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/FlareEnchant.java index de983e3..72a0fa3 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/FlareEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/FlareEnchant.java @@ -18,36 +18,42 @@ import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowData; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class FlareEnchant extends ExcellentEnchant implements Chanced, Arrowed, BowEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class FlareEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, BowEnchant { public static final String ID = "flare"; - private ChanceImplementation chanceImplementation; - private ArrowImplementation arrowImplementation; + private ChanceSettingsImpl chanceSettings; + private ArrowSettingsImpl arrowSettings; - public FlareEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); + public FlareEnchant(@NotNull ExcellentEnchantsPlugin plugin, File file) { + super(plugin, file); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to create a torch where arrow lands."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.4); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to create a torch where arrow lands."); + this.setMaxLevel(1); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100.0"); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.of(Particle.FIREWORKS_SPARK)); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.FIREWORKS_SPARK)); } @NotNull @@ -64,40 +70,38 @@ public class FlareEnchant extends ExcellentEnchant implements Chanced, Arrowed, @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } @NotNull @Override - public ArrowImplementation getArrowImplementation() { - return this.arrowImplementation; + public ArrowSettings getArrowSettings() { + return this.arrowSettings; } @Override public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - if (!(event.getProjectile() instanceof Arrow arrow)) return false; - if (!this.checkTriggerChance(level)) return false; + if (!(event.getProjectile() instanceof Arrow)) return false; - this.addData(arrow); - return true; + return this.checkTriggerChance(level); } @Override - public boolean onHit(@NotNull ProjectileHitEvent e, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { - Block block = e.getHitBlock(); + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + Block block = event.getHitBlock(); if (block == null) return false; - BlockFace face = e.getHitBlockFace(); + BlockFace face = event.getHitBlockFace(); if (face == null || face == BlockFace.DOWN) return false; Block relative = block.getRelative(face); if (!relative.getType().isAir()) return false; if (projectile.getShooter() instanceof Player player) { - BlockPlaceEvent event = new BlockPlaceEvent(relative, relative.getState(), block, new ItemStack(Material.TORCH), player,true, EquipmentSlot.HAND); - plugin.getPluginManager().callEvent(event); - if (event.isCancelled() || !event.canBuild()) return false; + BlockPlaceEvent placeEvent = new BlockPlaceEvent(relative, relative.getState(), block, new ItemStack(Material.TORCH), player,true, EquipmentSlot.HAND); + plugin.getPluginManager().callEvent(placeEvent); + if (placeEvent.isCancelled() || !placeEvent.canBuild()) return false; } if (face == BlockFace.UP) { diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantGhast.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/GhastEnchant.java similarity index 63% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantGhast.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/GhastEnchant.java index e162f55..56bb117 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/EnchantGhast.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/GhastEnchant.java @@ -12,36 +12,40 @@ import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; -public class EnchantGhast extends ExcellentEnchant implements BowEnchant, Chanced { +import java.io.File; + +public class GhastEnchant extends AbstractEnchantmentData implements ChanceData, BowEnchant { public static final String ID = "ghast"; - private boolean fireSpread; - private EnchantScaler yield; - private ChanceImplementation chanceImplementation; + private boolean fireSpread; + private Modifier yield; + private ChanceSettingsImpl chanceSettings; - public EnchantGhast(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Shoots fireballs instead of arrows."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.3); + public GhastEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Shoots fireballs instead of arrows."); + this.setMaxLevel(1); + this.setRarity(Rarity.UNCOMMON); - this.getDefaults().setConflicts( - EnchantEnderBow.ID, EnchantBomber.ID, - EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID, - EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID, + this.setConflicts( + EnderBowEnchant.ID, BomberEnchant.ID, + ExplosiveArrowsEnchant.ID, PoisonedArrowsEnchant.ID, ConfusingArrowsEnchant.ID, + WitheredArrowsEnchant.ID, ElectrifiedArrowsEnchant.ID, DragonfireArrowsEnchant.ID, DarknessArrowsEnchant.ID, VampiricArrowsEnchant.ID, - EnchantHover.ID, FlareEnchant.ID, + HoverEnchant.ID, FlareEnchant.ID, Enchantment.ARROW_FIRE.getKey().getKey(), Enchantment.ARROW_KNOCKBACK.getKey().getKey(), Enchantment.ARROW_DAMAGE.getKey().getKey() @@ -49,19 +53,22 @@ public class EnchantGhast extends ExcellentEnchant implements BowEnchant, Chance } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100"); - this.fireSpread = JOption.create("Settings.Fire_Spread", true, - "When 'true' creates fire on nearby blocks.").read(cfg); - this.yield = EnchantScaler.read(this, "Settings.Yield", "1.0 + " + Placeholders.ENCHANTMENT_LEVEL, + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); + + this.fireSpread = ConfigValue.create("Settings.Fire_Spread", + true, + "When 'true' creates fire on nearby blocks.").read(config); + + this.yield = Modifier.read(config, "Settings.Yield", + Modifier.add(2, 0, 1, 5), "Fireball explosion size/radius. The more value = the bigger the explosion."); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public boolean isFireSpread() { diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/HoverEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/HoverEnchant.java new file mode 100644 index 0000000..bea85a1 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/HoverEnchant.java @@ -0,0 +1,101 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.AbstractArrow; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.*; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class HoverEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, PotionData, BowEnchant { + + public static final String ID = "hover"; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public HoverEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.)"); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.BUBBLE_POP)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3, 3, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.LEVITATION, false, + Modifier.add(2, 1, 1, 15), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettingsImpl getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + if (!(event.getProjectile() instanceof Arrow arrow)) return false; + if (!this.checkTriggerChance(level)) return false; + + arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); + return arrow.addCustomEffect(this.createEffect(level), true); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/PoisonedArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/PoisonedArrowsEnchant.java new file mode 100644 index 0000000..e5b1784 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/PoisonedArrowsEnchant.java @@ -0,0 +1,101 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.AbstractArrow; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.*; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class PoisonedArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, PotionData, BowEnchant { + + public static final String ID = "poisoned_arrows"; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public PoisonedArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.)"); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.SLIME)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(7.5, 2.5, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.POISON, false, + Modifier.add(3, 1, 1, 300), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + if (!(event.getProjectile() instanceof Arrow arrow)) return false; + if (!this.checkTriggerChance(level)) return false; + + arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); + return arrow.addCustomEffect(this.createEffect(level), true); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/SniperEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/SniperEnchant.java index 21be4fc..2cd6f72 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/SniperEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/SniperEnchant.java @@ -11,47 +11,51 @@ import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class SniperEnchant extends ExcellentEnchant implements BowEnchant, Chanced { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SniperEnchant extends AbstractEnchantmentData implements BowEnchant, ChanceData { public static final String ID = "sniper"; - private static final String PLACEHOLDER_PROJECTILE_SPEED = "%enchantment_projectile_speed%"; + private ChanceSettingsImpl chanceSettings; + private Modifier speedModifier; - private ChanceImplementation chanceImplementation; - private EnchantScaler speedModifier; + public SniperEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); - public SniperEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - - this.getDefaults().setDescription("Increases projectile speed by " + PLACEHOLDER_PROJECTILE_SPEED + "%"); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.3); + this.setDescription("Increases projectile speed by " + GENERIC_AMOUNT + "%"); + this.setMaxLevel(5); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); - this.chanceImplementation = ChanceImplementation.create(this, "100.0"); - this.speedModifier = EnchantScaler.read(this, "Settings.Speed_Modifier", - "1.0 + " + Placeholders.ENCHANTMENT_LEVEL + " / 5.0", "Sets projectile's speed modifier."); + this.speedModifier = Modifier.read(config, "Settings.Speed_Modifier", + Modifier.add(1, 0.2, 1, 3D), + "Sets projectile's speed modifier."); - this.addPlaceholder(PLACEHOLDER_PROJECTILE_SPEED, level -> NumberUtil.format(this.getSpeedModifier(level) * 100D)); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getSpeedModifier(level) * 100D)); } @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } public double getSpeedModifier(int level) { diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/VampiricArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/VampiricArrowsEnchant.java index c9600bf..74dae03 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/VampiricArrowsEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/VampiricArrowsEnchant.java @@ -14,50 +14,54 @@ import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.EntityUtil; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowData; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.EntityUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class VampiricArrowsEnchant extends ExcellentEnchant implements BowEnchant, Arrowed, Chanced { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class VampiricArrowsEnchant extends AbstractEnchantmentData implements BowEnchant, ArrowData, ChanceData { public static final String ID = "vampiric_arrows"; - public static final String PLACEHOLDER_HEAL_AMOUNT = "%heal_amount%"; + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private Modifier healAmount; - private ArrowImplementation arrowImplementation; - private ChanceImplementation chanceImplementation; - private EnchantScaler healAmount; - - public VampiricArrowsEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to restore " + PLACEHOLDER_HEAL_AMOUNT + "❤ on arrow hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - this.getDefaults().setConflicts(EnchantEnderBow.ID, EnchantGhast.ID, EnchantBomber.ID); + public VampiricArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to restore " + GENERIC_AMOUNT + "❤ on arrow hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.redstone(Color.RED, 1f)); - this.arrowImplementation = ArrowImplementation.create(this, UniParticle.redstone(Color.RED, 1f)); + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(8, 4, 1, 100)); - this.chanceImplementation = ChanceImplementation.create(this, "20.0 * " + Placeholders.ENCHANTMENT_LEVEL); + this.healAmount = Modifier.read(config, "Settings.Heal_Amount", + Modifier.add(0, 1, 1, 10), + "Amount of health to be restored on hit." + ); - this.healAmount = EnchantScaler.read(this, "Settings.Heal_Amount", - Placeholders.ENCHANTMENT_LEVEL, - "Amount of health to be restored on hit."); - - this.addPlaceholder(PLACEHOLDER_HEAL_AMOUNT, level -> NumberUtil.format(this.getHealAmount(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getHealAmount(level))); } @NotNull @@ -68,14 +72,14 @@ public class VampiricArrowsEnchant extends ExcellentEnchant implements BowEnchan @NotNull @Override - public Arrowed getArrowImplementation() { - return this.arrowImplementation; + public ArrowSettings getArrowSettings() { + return this.arrowSettings; } @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } public double getHealAmount(int level) { @@ -90,11 +94,9 @@ public class VampiricArrowsEnchant extends ExcellentEnchant implements BowEnchan @Override public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { - if (!(event.getProjectile() instanceof Arrow arrow)) return false; - if (!this.checkTriggerChance(level)) return false; + if (!(event.getProjectile() instanceof Arrow)) return false; - this.addData(arrow); - return true; + return this.checkTriggerChance(level); } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/WitheredArrowsEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/WitheredArrowsEnchant.java new file mode 100644 index 0000000..177f6ab --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/bow/WitheredArrowsEnchant.java @@ -0,0 +1,101 @@ +package su.nightexpress.excellentenchants.enchantment.impl.bow; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.AbstractArrow; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.*; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ArrowSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class WitheredArrowsEnchant extends AbstractEnchantmentData implements ChanceData, ArrowData, PotionData, BowEnchant { + + public static final String ID = "withered_arrows"; + + private ArrowSettingsImpl arrowSettings; + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public WitheredArrowsEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch an arrow with " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.)"); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts(EnderBowEnchant.ID, GhastEnchant.ID, BomberEnchant.ID); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.arrowSettings = ArrowSettingsImpl.create(config, UniParticle.of(Particle.SPELL_WITCH)); + + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(4, 3, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.WITHER, false, + Modifier.add(3, 1, 1, 60), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ArrowSettings getArrowSettings() { + return arrowSettings; + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.BOW; + } + + @Override + public boolean onShoot(@NotNull EntityShootBowEvent event, @NotNull LivingEntity shooter, @NotNull ItemStack bow, int level) { + if (!(event.getProjectile() instanceof Arrow arrow)) return false; + if (!this.checkTriggerChance(level)) return false; + + arrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED); + return arrow.addCustomEffect(this.createEffect(level), true); + } + + @Override + public boolean onHit(@NotNull ProjectileHitEvent event, LivingEntity user, @NotNull Projectile projectile, @NotNull ItemStack bow, int level) { + return false; + } + + @Override + public boolean onDamage(@NotNull EntityDamageByEntityEvent event, @NotNull Projectile projectile, @NotNull LivingEntity shooter, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/AutoReelEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/AutoReelEnchant.java index dbc65fd..bcb7edd 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/AutoReelEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/AutoReelEnchant.java @@ -4,19 +4,28 @@ import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.FishingEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.FileConfig; -public class AutoReelEnchant extends ExcellentEnchant implements FishingEnchant { +import java.io.File; + +public class AutoReelEnchant extends AbstractEnchantmentData implements FishingEnchant { public static final String ID = "auto_reel"; - public AutoReelEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Automatically reels in a hook on bite."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(1.0); + public AutoReelEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Automatically reels in a hook on bite."); + this.setMaxLevel(1); + this.setRarity(Rarity.VERY_RARE); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + } @NotNull diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/CurseOfDrownedEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/CurseOfDrownedEnchant.java index ab2cd4a..fa4fc7c 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/CurseOfDrownedEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/CurseOfDrownedEnchant.java @@ -8,39 +8,44 @@ import org.bukkit.entity.FishHook; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.FishingEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class CurseOfDrownedEnchant extends ExcellentEnchant implements FishingEnchant, Chanced { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class CurseOfDrownedEnchant extends AbstractEnchantmentData implements FishingEnchant, ChanceData { public static final String ID = "curse_of_drowned"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public CurseOfDrownedEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to fish up a Drowned Zombie."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0D); + public CurseOfDrownedEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to fish up a Drowned Zombie."); + this.setMaxLevel(5); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "5.0 + " + Placeholders.ENCHANTMENT_LEVEL); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(0, 5, 1, 100)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @@ -62,7 +67,7 @@ public class CurseOfDrownedEnchant extends ExcellentEnchant implements FishingEn event.setCancelled(true); if (this.hasVisualEffects()) { - UniParticle.of(Particle.WATER_SPLASH).play(hook.getLocation(), 0.5, 0.1, 50); + UniParticle.of(Particle.WATER_SPLASH).play(hook.getLocation(), 0.75, 0.1, 50); UniSound.of(Sound.ENTITY_DROWNED_AMBIENT).play(event.getPlayer()); } return true; diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/DoubleCatchEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/DoubleCatchEnchant.java index 160f7dd..d0b7399 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/DoubleCatchEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/DoubleCatchEnchant.java @@ -6,31 +6,36 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.FishingEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class DoubleCatchEnchant extends ExcellentEnchant implements FishingEnchant, Chanced { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class DoubleCatchEnchant extends AbstractEnchantmentData implements FishingEnchant, ChanceData { public static final String ID = "double_catch"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public DoubleCatchEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Increases amount of caught item by x2 with " + Placeholders.ENCHANTMENT_CHANCE + "% chance."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); + public DoubleCatchEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Increases amount of caught item by x2 with " + ENCHANTMENT_CHANCE + "% chance."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 * " + Placeholders.ENCHANTMENT_LEVEL); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(4, 2, 1, 100)); } @NotNull @@ -47,8 +52,8 @@ public class DoubleCatchEnchant extends ExcellentEnchant implements FishingEncha @Override @NotNull - public ChanceImplementation getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/RiverMasterEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/RiverMasterEnchant.java index a29c9ab..5eaca17 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/RiverMasterEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/RiverMasterEnchant.java @@ -8,34 +8,37 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; -public class RiverMasterEnchant extends ExcellentEnchant implements GenericEnchant, EventListener { +import java.io.File; + +public class RiverMasterEnchant extends AbstractEnchantmentData implements GenericEnchant, SimpeListener { public static final String ID = "river_master"; - private EnchantScaler distanceMod; + private Modifier distanceMod; - public RiverMasterEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Increases casting distance."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.1); + public RiverMasterEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Increases casting distance."); + this.setMaxLevel(5); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.distanceMod = EnchantScaler.read(this, "Settings.Distance_Modifier", - "1.25 + " + Placeholders.ENCHANTMENT_LEVEL + " / 5", + protected void loadAdditional(@NotNull FileConfig config) { + this.distanceMod = Modifier.read(config, "Settings.Distance_Modifier", + Modifier.add(1, 0.25, 1, 3D), "Multiplies the casted fish hook's velocity by specified value.", - "Setting too high values will result in hook auto removal by vanilla game/server mechanics."); + "Setting too high values will result in hook auto removal by vanilla game/server mechanics." + ); } @NotNull @@ -56,7 +59,7 @@ public class RiverMasterEnchant extends ExcellentEnchant implements GenericEncha ItemStack rod = EnchantUtils.getFishingRod(player); if (rod == null) return; - int level = EnchantUtils.getLevel(rod, this.getBackend()); + int level = EnchantUtils.getLevel(rod, this.getEnchantment()); if (level < 1) return; if (this.isOutOfCharges(rod)) return; diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SeasonedAnglerEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SeasonedAnglerEnchant.java index 2398fb8..fcd4099 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SeasonedAnglerEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SeasonedAnglerEnchant.java @@ -4,38 +4,42 @@ import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.FishingEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class SeasonedAnglerEnchant extends ExcellentEnchant implements FishingEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SeasonedAnglerEnchant extends AbstractEnchantmentData implements FishingEnchant { public static final String ID = "seasoned_angler"; - private EnchantScaler expMod; + private Modifier xpModifier; - public SeasonedAnglerEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Increases amount of XP gained from fishing by " + Placeholders.GENERIC_AMOUNT + "%."); - this.getDefaults().setLevelMax(4); - this.getDefaults().setTier(0.1); + public SeasonedAnglerEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Increases amount of XP gained from fishing by " + GENERIC_AMOUNT + "%."); + this.setMaxLevel(4); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.expMod = EnchantScaler.read(this, "Settings.Exp_Percent", - "25.0 * " + Placeholders.ENCHANTMENT_LEVEL, + protected void loadAdditional(@NotNull FileConfig config) { + this.xpModifier = Modifier.read(config, "Settings.XP_Modifier", + Modifier.add(0, 25, 1, 300), "Amount (in percent) of additional XP from fishing."); - this.addPlaceholder(Placeholders.GENERIC_AMOUNT, level -> NumberUtil.format(this.getExpPercent(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getXPPercent(level))); } - public int getExpPercent(int level) { - return (int) this.expMod.getValue(level); + public int getXPPercent(int level) { + return (int) this.xpModifier.getValue(level); } @NotNull @@ -50,7 +54,7 @@ public class SeasonedAnglerEnchant extends ExcellentEnchant implements FishingEn if (event.getExpToDrop() == 0) return false; int expDrop = event.getExpToDrop(); - int expPercent = this.getExpPercent(level); + int expPercent = this.getXPPercent(level); int expModified = (int) Math.ceil(expDrop * (1D + expPercent / 100D)); event.setExpToDrop(expModified); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SurvivalistEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SurvivalistEnchant.java index c9ab4d0..1aa37de 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SurvivalistEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/fishing/SurvivalistEnchant.java @@ -7,40 +7,43 @@ import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.inventory.CookingRecipe; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.FishingEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import java.io.File; import java.util.HashSet; import java.util.Set; -public class SurvivalistEnchant extends ExcellentEnchant implements FishingEnchant, Chanced { +public class SurvivalistEnchant extends AbstractEnchantmentData implements FishingEnchant, ChanceData { public static final String ID = "survivalist"; private final Set> cookingRecipes; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public SurvivalistEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Automatically cooks fish if what is caught is raw."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.4); + public SurvivalistEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Automatically cooks fish if what is caught is raw."); + this.setMaxLevel(1); + this.setRarity(Rarity.UNCOMMON); this.cookingRecipes = new HashSet<>(); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); this.cookingRecipes.clear(); this.plugin.getServer().recipeIterator().forEachRemaining(recipe -> { - if (recipe instanceof CookingRecipe cookingRecipe) { + if (recipe instanceof CookingRecipe cookingRecipe && cookingRecipe.getInput().getType().isItem()) { this.cookingRecipes.add(cookingRecipe); } }); @@ -48,8 +51,8 @@ public class SurvivalistEnchant extends ExcellentEnchant implements FishingEncha @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @@ -72,7 +75,7 @@ public class SurvivalistEnchant extends ExcellentEnchant implements FishingEncha ItemStack stack = drop.getItemStack(); - CookingRecipe recipe = this.cookingRecipes.stream().filter(r -> r.getInput().isSimilar(stack)).findFirst().orElse(null); + CookingRecipe recipe = this.cookingRecipes.stream().filter(rec -> rec.getInputChoice().test(stack)).findFirst().orElse(null); if (recipe == null) return false; ItemStack cooked = recipe.getResult(); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/ArrowImplementation.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/ArrowImplementation.java deleted file mode 100644 index c4aaf56..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/ArrowImplementation.java +++ /dev/null @@ -1,87 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.meta; - -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.entity.Projectile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.utils.PDCUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchantsAPI; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.task.ArrowTrailsTask; - -import java.util.Optional; - -public final class ArrowImplementation implements Arrowed { - - private final ExcellentEnchant enchant; - private final NamespacedKey projectileKey; - - private final UniParticle trailParticle; - - private ArrowImplementation(@NotNull ExcellentEnchant enchant, @Nullable UniParticle trailParticle) { - this.enchant = enchant; - this.projectileKey = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "arrow.enchant_id"); - this.trailParticle = trailParticle; - } - - @NotNull - public static ArrowImplementation create(@NotNull ExcellentEnchant enchant) { - return create(enchant, UniParticle.of(Particle.REDSTONE)); - } - - @NotNull - public static ArrowImplementation create(@NotNull ExcellentEnchant enchant, @NotNull UniParticle particle) { - JYML cfg = enchant.getConfig(); - - UniParticle effect = new JOption<>("Settings.Arrow.Trail_Effect", - (cfg1, path, def) -> UniParticle.read(cfg1, path), - particle, - "Sets particle effect for the arrow trail of this enchantment." - ).setWriter((cfg1, path, particle1) -> particle1.write(cfg1, path)).read(cfg); - - return new ArrowImplementation(enchant, effect); - } - - @Override - @NotNull - public Arrowed getArrowImplementation() { - return this; - } - - @Override - public void addTrail(@NotNull Projectile projectile) { - if (!this.enchant.hasVisualEffects()) return; - if (this.getTrailParticle().isEmpty()) return; - - this.getTrailParticle().ifPresent(particle -> { - ArrowTrailsTask.add(projectile, particle); - }); - } - - @NotNull - @Override - public Optional getTrailParticle() { - return trailParticle == null ? Optional.empty() : Optional.of(trailParticle); - } - - @NotNull - public NamespacedKey getProjectileKey() { - return projectileKey; - } - - @Override - public void addData(@NotNull Projectile projectile) { - PDCUtil.set(projectile, this.getProjectileKey(), this.enchant.getId()); - } - - @Override - public boolean isOurProjectile(@NotNull Projectile projectile) { - String enchantId = PDCUtil.getString(projectile, this.getProjectileKey()).orElse(null); - return this.enchant.getId().equalsIgnoreCase(enchantId); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/ChanceImplementation.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/ChanceImplementation.java deleted file mode 100644 index c1bad7f..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/ChanceImplementation.java +++ /dev/null @@ -1,45 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.meta; - -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; - -public final class ChanceImplementation implements Chanced { - - //private final ExcellentEnchant enchant; - private final EnchantScaler triggerChance; - - private ChanceImplementation(@NotNull ExcellentEnchant enchant, @NotNull EnchantScaler triggerChance) { - //this.enchant = enchant; - this.triggerChance = triggerChance; - } - - @NotNull - public static ChanceImplementation create(@NotNull ExcellentEnchant enchant) { - return create(enchant, "100"); - } - - @NotNull - public static ChanceImplementation create(@NotNull ExcellentEnchant enchant, @NotNull String def) { - return new ChanceImplementation(enchant, EnchantScaler.read(enchant, "Settings.Trigger_Chance", def, - "A chance that this enchantment will be triggered.")); - } - - @Override - @NotNull - public Chanced getChanceImplementation() { - return this; - } - - @Override - public double getTriggerChance(int level) { - return this.triggerChance.getValue(level); - } - - @Override - public boolean checkTriggerChance(int level) { - return Rnd.chance(this.getTriggerChance(level)); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/PeriodImplementation.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/PeriodImplementation.java deleted file mode 100644 index a7219f1..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/PeriodImplementation.java +++ /dev/null @@ -1,56 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.meta; - -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.meta.Periodic; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; - -public class PeriodImplementation implements Periodic { - - private final EnchantScaler triggerInterval; - - private long nextTriggerTime; - - public PeriodImplementation(@NotNull ExcellentEnchant enchant, @NotNull EnchantScaler triggerInterval) { - this.triggerInterval = triggerInterval; - this.updateTriggerTime(); - } - - @NotNull - public static PeriodImplementation create(@NotNull ExcellentEnchant enchant) { - return create(enchant, "100"); - } - - @NotNull - public static PeriodImplementation create(@NotNull ExcellentEnchant enchant, @NotNull String def) { - return new PeriodImplementation(enchant, EnchantScaler.read(enchant, "Settings.Trigger_Interval", def, - "Sets how often (in ticks) this enchantment will be triggered.", - "20 ticks = 1 second.")); - } - - @NotNull - @Override - public Periodic getPeriodImplementation() { - return this; - } - - @Override - public long getInterval() { - return (long) this.triggerInterval.getValue(1); - } - - @Override - public long getNextTriggerTime() { - return nextTriggerTime; - } - - @Override - public boolean isTriggerTime() { - return System.currentTimeMillis() >= this.getNextTriggerTime(); - } - - @Override - public void updateTriggerTime() { - this.nextTriggerTime = System.currentTimeMillis() + this.getInterval() * 50L - 100L; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/PotionImplementation.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/PotionImplementation.java deleted file mode 100644 index a15c83d..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/meta/PotionImplementation.java +++ /dev/null @@ -1,91 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.meta; - -import org.bukkit.entity.LivingEntity; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; - -public final class PotionImplementation implements Potioned { - - private final ExcellentEnchant enchant; - private final PotionEffectType effectType; - private final EnchantScaler duration; - private final EnchantScaler amplifier; - private final boolean isPermanent; - - private PotionImplementation(@NotNull ExcellentEnchant enchant, - @NotNull PotionEffectType effectType, boolean isPermanent, - @NotNull EnchantScaler duration, @NotNull EnchantScaler amplifier) { - this.enchant = enchant; - this.effectType = effectType; - this.duration = duration; - this.amplifier = amplifier; - this.isPermanent = isPermanent; - } - - @Override - @NotNull - public Potioned getPotionImplementation() { - return this; - } - - public static PotionImplementation create(@NotNull ExcellentEnchant enchant, @NotNull PotionEffectType type, boolean isPermanent) { - return create(enchant, type, isPermanent, "5 * " + Placeholders.ENCHANTMENT_LEVEL, Placeholders.ENCHANTMENT_LEVEL); - } - - public static PotionImplementation create(@NotNull ExcellentEnchant enchant, - @NotNull PotionEffectType type, boolean isPermanent, - @NotNull String duration, @NotNull String amplifier) { - - EnchantScaler durationScale = EnchantScaler.read(enchant, "Settings.Potion_Effect.Duration", duration, - "Potion effect duration (in seconds). This setting is useless for 'permanent' effects."); - - EnchantScaler amplifierScale = EnchantScaler.read(enchant, "Settings.Potion_Effect.Level", amplifier, - "Potion effect level."); - - return new PotionImplementation(enchant, type, isPermanent, durationScale, amplifierScale); - } - - @Override - public boolean isPermanent() { - return this.isPermanent; - } - - @NotNull - public PotionEffectType getEffectType() { - return this.effectType; - } - - public int getEffectDuration(int level) { - if (this.isPermanent()) { - int duration = Config.TASKS_PASSIVE_ENCHANTS_TRIGGER_INTERVAL.get().intValue() * 2; - if (this.getEffectType().getName().equalsIgnoreCase(PotionEffectType.NIGHT_VISION.getName()) && duration < 600) { - duration += 30 * 20; - } - return duration; - } - return (int) (this.duration.getValue(level) * 20); - } - - public int getEffectAmplifier(int level) { - return (int) this.amplifier.getValue(level); - } - - @NotNull - public PotionEffect createEffect(int level) { - int duration = this.getEffectDuration(level); - int amplifier = Math.max(0, this.getEffectAmplifier(level) - 1); - - return new PotionEffect(this.getEffectType(), duration, amplifier, false, this.enchant.hasVisualEffects()); - } - - public boolean addEffect(@NotNull LivingEntity target, int level) { - target.addPotionEffect(this.createEffect(level)); - return true; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/BlastMiningEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/BlastMiningEnchant.java index fd5ebda..43245df 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/BlastMiningEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/BlastMiningEnchant.java @@ -13,64 +13,65 @@ import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.NumberUtil; +import java.io.File; import java.util.List; -public class BlastMiningEnchant extends ExcellentEnchant implements Chanced, BlockBreakEnchant, EventListener { +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class BlastMiningEnchant extends AbstractEnchantmentData implements ChanceData, BlockBreakEnchant, SimpeListener { public static final String ID = "blast_mining"; - public static final String PLACEHOLDER_EXPLOSION_POWER = "%enchantment_explosion_power%"; - private EnchantScaler explosionPower; - private EnchantScaler minBlockStrength; - private ChanceImplementation chanceImplementation; + private Modifier explosionPower; + private Modifier minBlockStrength; + private ChanceSettingsImpl chanceSettings; private int explodeLevel; - public BlastMiningEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to mine blocks by explosion."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(1.0); - this.getDefaults().setConflicts(VeinminerEnchant.ID, TunnelEnchant.ID); + public BlastMiningEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to mine blocks by explosion."); + this.setMaxLevel(5); + this.setRarity(Rarity.RARE); + this.setConflicts(VeinminerEnchant.ID, TunnelEnchant.ID); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.multiply(10, 1, 1, 100)); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 * " + Placeholders.ENCHANTMENT_LEVEL); - - this.explosionPower = EnchantScaler.read(this, "Settings.Explosion.Power", - "3.0 + (" + Placeholders.ENCHANTMENT_LEVEL + " - 1.0 * 0.25)", + this.explosionPower = Modifier.read(config, "Settings.Explosion.Power", + Modifier.add(3, 0.75, 1, 8), "Explosion power. The more power = the more blocks (area) to explode."); - this.minBlockStrength = EnchantScaler.read(this, "Settings.Min_Block_Strength", - "1.5 - " + Placeholders.ENCHANTMENT_LEVEL + " / 10", + this.minBlockStrength = Modifier.read(config, "Settings.Min_Block_Strength", + Modifier.add(1.5, -0.1, 1), "Minimal block strength value for the enchantment to have effect.", "Block strength value is how long it takes to break the block by a hand.", "For example, a Stone has 3.0 strength."); - this.addPlaceholder(PLACEHOLDER_EXPLOSION_POWER, level -> NumberUtil.format(this.getExplosionPower(level))); + this.addPlaceholder(GENERIC_RADIUS, level -> NumberUtil.format(this.getExplosionPower(level))); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public double getExplosionPower(int level) { @@ -88,7 +89,7 @@ public class BlastMiningEnchant extends ExcellentEnchant implements Chanced, Blo @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.PICKAXE}; } @@ -134,17 +135,17 @@ public class BlastMiningEnchant extends ExcellentEnchant implements Chanced, Blo } // Do not damage around entities by enchantment explosion. - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlastExplosionDamage(EntityDamageByEntityEvent e) { - if (e.getCause() != DamageCause.ENTITY_EXPLOSION) return; - if (!(e.getDamager() instanceof Player player)) return; + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlastExplosionDamage(EntityDamageByEntityEvent event) { + if (event.getCause() != DamageCause.ENTITY_EXPLOSION) return; + if (!(event.getDamager() instanceof Player)) return; - e.setCancelled(this.explodeLevel > 0); + event.setCancelled(this.explodeLevel > 0); } // Do not reduce item durability for 'exploded' blocks. - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlastExplosionItemDamage(PlayerItemDamageEvent e) { - e.setCancelled(this.explodeLevel > 0); + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onBlastExplosionItemDamage(PlayerItemDamageEvent event) { + event.setCancelled(this.explodeLevel > 0); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfBreakingEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfBreakingEnchant.java index fae2ab2..0941525 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfBreakingEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfBreakingEnchant.java @@ -7,42 +7,46 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.NumberUtil; -public class CurseOfBreakingEnchant extends ExcellentEnchant implements GenericEnchant, EventListener, Chanced { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class CurseOfBreakingEnchant extends AbstractEnchantmentData implements GenericEnchant, SimpeListener, ChanceData { public static final String ID = "curse_of_breaking"; - public static final String PLACEHOLDER_DURABILITY_AMOUNT = "%enchantment_durability_amount%"; - private EnchantScaler durabilityAmount; - private ChanceImplementation chanceImplementation; + private Modifier durabilityAmount; + private ChanceSettingsImpl chanceSettings; - public CurseOfBreakingEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to consume extra " + PLACEHOLDER_DURABILITY_AMOUNT + " durability points."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0D); + public CurseOfBreakingEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to consume extra " + GENERIC_AMOUNT + " durability points."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.durabilityAmount = EnchantScaler.read(this, "Settings.Durability_Amount", - Placeholders.ENCHANTMENT_LEVEL, + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.multiply(10, 1, 1, 100)); + + this.durabilityAmount = Modifier.read(config, "Settings.Durability_Amount", + Modifier.add(0, 1, 1, 5), "Amount of durability points to be taken from the item."); - this.addPlaceholder(PLACEHOLDER_DURABILITY_AMOUNT, level -> NumberUtil.format(this.getDurabilityAmount(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getDurabilityAmount(level))); } @Override @@ -52,8 +56,8 @@ public class CurseOfBreakingEnchant extends ExcellentEnchant implements GenericE @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public int getDurabilityAmount(int level) { @@ -72,7 +76,7 @@ public class CurseOfBreakingEnchant extends ExcellentEnchant implements GenericE if (!this.isAvailableToUse(player)) return; ItemStack item = event.getItem(); - int level = EnchantUtils.getLevel(item, this.getBackend()); + int level = EnchantUtils.getLevel(item, this.getEnchantment()); if (level < 1) return; if (!this.checkTriggerChance(level)) return; diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMediocrityEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMediocrityEnchant.java index fe9de55..4fecebd 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMediocrityEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMediocrityEnchant.java @@ -9,33 +9,40 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.ItemUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.ItemUtil; -public class CurseOfMediocrityEnchant extends ExcellentEnchant implements Chanced, BlockDropEnchant, DeathEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class CurseOfMediocrityEnchant extends AbstractEnchantmentData implements ChanceData, BlockDropEnchant, DeathEnchant { public static final String ID = "curse_of_mediocrity"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public CurseOfMediocrityEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to disenchant item drops."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0D); + public CurseOfMediocrityEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to disenchant item drops."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "25.0 * " + Placeholders.ENCHANTMENT_LEVEL); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.multiply(15, 1, 1, 100)); } @NotNull @@ -46,7 +53,7 @@ public class CurseOfMediocrityEnchant extends ExcellentEnchant implements Chance @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[] { ItemCategory.SWORD, ItemCategory.BOW, ItemCategory.CROSSBOW, ItemCategory.TRIDENT, ItemCategory.TOOL }; @@ -60,8 +67,8 @@ public class CurseOfMediocrityEnchant extends ExcellentEnchant implements Chance @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } @Override @@ -70,15 +77,12 @@ public class CurseOfMediocrityEnchant extends ExcellentEnchant implements Chance } @Override - public boolean onDrop(@NotNull BlockDropItemEvent event, - @NotNull LivingEntity player, @NotNull ItemStack item, int level) { + public boolean onDrop(@NotNull BlockDropItemEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { if (!this.checkTriggerChance(level)) return false; event.getItems().forEach(drop -> { ItemStack stack = drop.getItemStack(); - ItemUtil.mapMeta(stack, meta -> { - meta.getEnchants().keySet().forEach(meta::removeEnchant); - }); + EnchantUtils.removeAll(stack); drop.setItemStack(stack); }); @@ -100,7 +104,7 @@ public class CurseOfMediocrityEnchant extends ExcellentEnchant implements Chance if (!this.checkTriggerChance(level)) return false; event.getDrops().forEach(stack -> { - ItemUtil.mapMeta(stack, meta -> { + ItemUtil.editMeta(stack, meta -> { meta.getEnchants().keySet().forEach(meta::removeEnchant); }); }); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMisfortuneEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMisfortuneEnchant.java index 1c1d833..34dbd48 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMisfortuneEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/CurseOfMisfortuneEnchant.java @@ -2,7 +2,6 @@ package su.nightexpress.excellentenchants.enchantment.impl.tool; import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventPriority; @@ -11,56 +10,64 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; -public class CurseOfMisfortuneEnchant extends ExcellentEnchant implements Chanced, BlockBreakEnchant, DeathEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class CurseOfMisfortuneEnchant extends AbstractEnchantmentData implements ChanceData, BlockBreakEnchant, DeathEnchant { public static final String ID = "curse_of_misfortune"; - private boolean dropExp; - private ChanceImplementation chanceImplementation; + private boolean dropXP; + private ChanceSettingsImpl chanceImplementation; - public CurseOfMisfortuneEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to have no drops from blocks or mobs."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0D); - this.getDefaults().setConflicts( + public CurseOfMisfortuneEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to have no drops from blocks or mobs."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); + this.setConflicts( Enchantment.LOOT_BONUS_BLOCKS.getKey().getKey(), Enchantment.LOOT_BONUS_MOBS.getKey().getKey() ); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.dropExp = JOption.create("Settings.Drop_Exp", false, - "When 'true' allows to drop exp from mobs/blocks.").read(cfg); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceImplementation = ChanceSettingsImpl.create(config, Modifier.multiply(7, 1, 1, 100)); + + this.dropXP = ConfigValue.create("Settings.Drop_XP", + false, + "Sets whether or not XP from blocks and mobs can be dropped when enchantment applies." + ).read(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { + public ChanceSettings getChanceSettings() { return chanceImplementation; } - public boolean isDropExp() { - return dropExp; + public boolean isDropXP() { + return dropXP; } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[] { ItemCategory.SWORD, ItemCategory.BOW, ItemCategory.CROSSBOW, ItemCategory.TRIDENT, ItemCategory.TOOL }; @@ -94,7 +101,7 @@ public class CurseOfMisfortuneEnchant extends ExcellentEnchant implements Chance if (!this.checkTriggerChance(level)) return false; event.setDropItems(false); - if (!this.isDropExp()) event.setExpToDrop(0); + if (!this.isDropXP()) event.setExpToDrop(0); return true; } @@ -103,7 +110,7 @@ public class CurseOfMisfortuneEnchant extends ExcellentEnchant implements Chance if (!this.checkTriggerChance(level)) return false; event.getDrops().clear(); - if (!this.isDropExp()) event.setDroppedExp(0); + if (!this.isDropXP()) event.setDroppedExp(0); return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/HasteEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/HasteEnchant.java index 2f10391..efb3bc0 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/HasteEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/HasteEnchant.java @@ -5,45 +5,51 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.PeriodicSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PeriodImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.PeriodSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class HasteEnchant extends ExcellentEnchant implements Potioned, PassiveEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class HasteEnchant extends AbstractEnchantmentData implements PotionData, PassiveEnchant { public static final String ID = "haste"; - private PotionImplementation potionImplementation; - private PeriodImplementation periodImplementation; + private PotionSettingsImpl potionSettings; + private PeriodSettingsImpl periodSettings; - public HasteEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); + public HasteEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Grants permanent " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " effect."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.FAST_DIGGING, true); - this.periodImplementation = PeriodImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.FAST_DIGGING, true); + this.periodSettings = PeriodSettingsImpl.create(config); } @NotNull @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; + public PotionSettings getPotionSettings() { + return potionSettings; } @NotNull @Override - public PeriodImplementation getPeriodImplementation() { - return periodImplementation; + public PeriodicSettings getPeriodSettings() { + return periodSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/LuckyMinerEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/LuckyMinerEnchant.java index 79beb75..c186a87 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/LuckyMinerEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/LuckyMinerEnchant.java @@ -5,56 +5,61 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class LuckyMinerEnchant extends ExcellentEnchant implements Chanced, BlockBreakEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class LuckyMinerEnchant extends AbstractEnchantmentData implements ChanceData, BlockBreakEnchant { public static final String ID = "lucky_miner"; - private static final String PLACEHOLDER_EXP_MODIFIER = "%enchantment_exp_modifier%"; - private EnchantScaler expModifier; - private ChanceImplementation chanceImplementation; + private Modifier xpModifier; + private ChanceSettingsImpl chanceSettings; - public LuckyMinerEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to gain " + PLACEHOLDER_EXP_MODIFIER + "% more exp from ores."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.1); + public LuckyMinerEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to gain " + GENERIC_AMOUNT + "% more XP from ores."); + this.setMaxLevel(5); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "30.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 7.0"); - this.expModifier = EnchantScaler.read(this, "Settings.Exp_Modifier", - "1.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.5", - "Exp modifier value. The original exp amount will be multiplied on this value."); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(25, 7.5, 1, 100)); - this.addPlaceholder(PLACEHOLDER_EXP_MODIFIER, level -> NumberUtil.format(this.getExpModifier(level) * 100D - 100D)); + this.xpModifier = Modifier.read(config, "Settings.Exp_Modifier", + Modifier.add(1, 0.5, 1, 5), + "XP Modifier. Amount of dropped XP will be multiplied on this value." + ); + + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getXPModifier(level) * 100D - 100D)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } - public double getExpModifier(int level) { - return this.expModifier.getValue(level); + public double getXPModifier(int level) { + return this.xpModifier.getValue(level); } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.PICKAXE}; } @@ -68,7 +73,7 @@ public class LuckyMinerEnchant extends ExcellentEnchant implements Chanced, Bloc public boolean onBreak(@NotNull BlockBreakEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { if (!this.checkTriggerChance(level)) return false; - double expMod = this.getExpModifier(level); + double expMod = this.getXPModifier(level); event.setExpToDrop((int) ((double) event.getExpToDrop() * expMod)); return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/ReplanterEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/ReplanterEnchant.java index e1ddd78..c164599 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/ReplanterEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/ReplanterEnchant.java @@ -16,53 +16,62 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; import su.nightexpress.excellentenchants.api.enchantment.type.InteractEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniSound; +import java.io.File; import java.util.Set; -public class ReplanterEnchant extends ExcellentEnchant implements Chanced, InteractEnchant, BlockBreakEnchant { +public class ReplanterEnchant extends AbstractEnchantmentData implements ChanceData, InteractEnchant, BlockBreakEnchant { public static final String ID = "replanter"; private boolean replantOnRightClick; private boolean replantOnPlantBreak; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; private static final Set CROPS = Set.of( Material.WHEAT_SEEDS, Material.BEETROOT_SEEDS, Material.MELON_SEEDS, Material.PUMPKIN_SEEDS, Material.POTATO, Material.CARROT, Material.NETHER_WART); - public ReplanterEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Automatically replant crops on right click and when harvest."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.3); + public ReplanterEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Automatically replant crops on right click and when harvest."); + this.setMaxLevel(1); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100"); - this.replantOnRightClick = JOption.create("Settings.Replant.On_Right_Click", true, - "When 'true', player will be able to replant crops when right-clicking farmland blocks.").read(cfg); - this.replantOnPlantBreak = JOption.create("Settings.Replant.On_Plant_Break", true, - "When 'true', crops will be automatically replanted when player break plants with enchanted tool in hand.").read(cfg); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); + + this.replantOnRightClick = ConfigValue.create("Settings.Replant.On_Right_Click", + true, + "When 'true', player will be able to replant crops when right-clicking farmland blocks." + ).read(config); + + this.replantOnPlantBreak = ConfigValue.create("Settings.Replant.On_Plant_Break", + true, + "When 'true', crops will be automatically replanted when player break plants with enchanted tool in hand." + ).read(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public boolean isReplantOnPlantBreak() { @@ -75,29 +84,10 @@ public class ReplanterEnchant extends ExcellentEnchant implements Chanced, Inter @NotNull private Material fineSeedsToBlock(@NotNull Material material) { - if (material == Material.POTATO) return Material.POTATOES; - if (material == Material.CARROT) return Material.CARROTS; - if (material == Material.BEETROOT_SEEDS) return Material.BEETROOTS; - if (material == Material.WHEAT_SEEDS) return Material.WHEAT; - if (material == Material.PUMPKIN_SEEDS) return Material.PUMPKIN_STEM; - if (material == Material.MELON_SEEDS) return Material.MELON_STEM; - return material; - } - - @NotNull - private Material fineBlockToSeeds(@NotNull Material material) { - if (material == Material.POTATOES) return Material.POTATO; - if (material == Material.CARROTS) return Material.CARROT; - if (material == Material.BEETROOTS) return Material.BEETROOT_SEEDS; - if (material == Material.WHEAT) return Material.WHEAT_SEEDS; - if (material == Material.MELON_STEM) return Material.MELON_SEEDS; - if (material == Material.PUMPKIN_STEM) return Material.PUMPKIN_SEEDS; - return material; + return plugin.getEnchantNMS().getItemBlockVariant(material); } private boolean takeSeeds(@NotNull Player player, @NotNull Material material) { - material = this.fineBlockToSeeds(material); - int slot = player.getInventory().first(material); if (slot < 0) return false; @@ -110,7 +100,7 @@ public class ReplanterEnchant extends ExcellentEnchant implements Chanced, Inter @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.HOE}; } @@ -171,25 +161,17 @@ public class ReplanterEnchant extends ExcellentEnchant implements Chanced, Inter if (!this.checkTriggerChance(level)) return false; Block blockPlant = event.getBlock(); - //if (EnchantTelekinesis.isDropHandled(blockPlant)) return false; - //if (EnchantRegister.TELEKINESIS != null && item.containsEnchantment(EnchantRegister.TELEKINESIS)) return false; // Check if broken block is supported crop(s). - if (!CROPS.contains(this.fineBlockToSeeds(blockPlant.getType()))) return false; + if (!CROPS.contains(blockPlant.getBlockData().getPlacementMaterial())) return false; // Check if broken block is actually can grow. BlockData dataPlant = blockPlant.getBlockData(); if (!(dataPlant instanceof Ageable plant)) return false; - // Check if crop is not at its maximal age to prevent accidient replant. - /*if (plant.getAge() < plant.getMaximumAge()) { - e.setCancelled(true); - return false; - }*/ - // Replant the gathered crops with a new one. - if (this.takeSeeds(player, plant.getMaterial())) { - plugin.getServer().getScheduler().runTask(plugin, () -> { + if (this.takeSeeds(player, dataPlant.getPlacementMaterial())) { + plugin.runTask(task -> { blockPlant.setType(plant.getMaterial()); plant.setAge(0); blockPlant.setBlockData(plant); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkChestEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkChestEnchant.java index ef0e0c4..e2e8b67 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkChestEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkChestEnchant.java @@ -20,53 +20,66 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BlockStateMeta; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.ItemUtil; -import su.nexmedia.engine.utils.PDCUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.ItemReplacer; +import su.nightexpress.nightcore.util.PDCUtil; +import su.nightexpress.nightcore.util.Plugins; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; -public class SilkChestEnchant extends ExcellentEnchant implements BlockDropEnchant, EventListener { +public class SilkChestEnchant extends AbstractEnchantmentData implements BlockDropEnchant, SimpeListener { public static final String ID = "silk_chest"; - private String chestName; - private List chestLore; - private final NamespacedKey keyChest; + private String chestName; + private List chestLore; + private final NamespacedKey keyChest; - public SilkChestEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Drop chests and saves all its content."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.5); + public SilkChestEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Drop chests and saves all its content."); + this.setMaxLevel(1); + this.setRarity(Rarity.VERY_RARE); this.keyChest = new NamespacedKey(plugin, ID + ".item"); } @Override - public void loadSettings() { - super.loadSettings(); - this.chestName = JOption.create("Settings.Chest_Item.Name", "Chest &7(" + Placeholders.GENERIC_AMOUNT + " items)", + public boolean checkServerRequirements() { + if (Plugins.isSpigot()) { + this.warn("Enchantment can only be used in PaperMC or Paper based forks."); + return false; + } + return true; + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chestName = ConfigValue.create("Settings.Chest_Item.Name", "Chest (" + Placeholders.GENERIC_AMOUNT + " items)", "Chest item display name.", - "Use '" + Placeholders.GENERIC_AMOUNT + "' for items amount.").mapReader(Colorizer::apply).read(cfg); - this.chestLore = JOption.create("Settings.Chest_Item.Lore", new ArrayList<>(), + "Use '" + Placeholders.GENERIC_AMOUNT + "' for items amount." + ).read(config); + + this.chestLore = ConfigValue.create("Settings.Chest_Item.Lore", new ArrayList<>(), "Chest item lore.", - "Use '" + Placeholders.GENERIC_AMOUNT + "' for items amount.").mapReader(Colorizer::apply).read(cfg); + "Use '" + Placeholders.GENERIC_AMOUNT + "' for items amount." + ).read(config); } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.AXE}; } @@ -76,12 +89,6 @@ public class SilkChestEnchant extends ExcellentEnchant implements BlockDropEncha return EnchantmentTarget.TOOL; } - @NotNull - @Override - public EventPriority getDropPriority() { - return EventPriority.NORMAL; - } - public boolean isSilkChest(@NotNull ItemStack item) { return PDCUtil.getBoolean(item, this.keyChest).isPresent(); } @@ -104,43 +111,15 @@ public class SilkChestEnchant extends ExcellentEnchant implements BlockDropEncha stateMeta.setLore(this.chestLore); chestStack.setItemMeta(stateMeta); - ItemUtil.replace(chestStack, str -> str.replace(Placeholders.GENERIC_AMOUNT, String.valueOf(amount))); + ItemReplacer.replace(chestStack, str -> str.replace(Placeholders.GENERIC_AMOUNT, String.valueOf(amount))); PDCUtil.set(chestStack, this.keyChest, true); return chestStack; - - // Store and count chest items. - /*int amount = 0; - int count = 0; - for (ItemStack itemInv : chest.getBlockInventory().getContents()) { - if (itemInv == null) itemInv = new ItemStack(Material.AIR); - else amount++; - - String base64 = ItemUtil.toBase64(itemInv); - if (base64 == null) continue; - if (base64.length() >= Short.MAX_VALUE) { - chest.getWorld().dropItemNaturally(chest.getLocation(), itemInv); - continue; - } - PDCUtil.setData(chestItem, this.getItemKey(count++), base64); - } - - // Apply item meta name and items data string. - ItemMeta meta = chestItem.getItemMeta(); - if (meta != null) { - String nameOrig = ItemUtil.getItemName(chestItem); - String nameChest = this.chestName.replace("%name%", nameOrig).replace("%items%", String.valueOf(amount)); - meta.setDisplayName(nameChest); - chestItem.setItemMeta(meta); - } - - return chestItem;*/ } @Override public boolean onDrop(@NotNull BlockDropItemEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { BlockState state = event.getBlockState(); - Block block = state.getBlock(); if (!(state instanceof Chest chest)) return false; @@ -150,11 +129,11 @@ public class SilkChestEnchant extends ExcellentEnchant implements BlockDropEncha event.getItems().clear(); if (chest.getBlockInventory().isEmpty()) { - EnchantUtils.popResource(event, new ItemStack(chest.getType())); + this.plugin.populateResource(event, new ItemStack(chest.getType())); return false; } - EnchantUtils.popResource(event, this.getSilkChest(chest)); + this.plugin.populateResource(event, this.getSilkChest(chest)); chest.getBlockInventory().clear(); @@ -162,11 +141,11 @@ public class SilkChestEnchant extends ExcellentEnchant implements BlockDropEncha } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onSilkChestPlace(BlockPlaceEvent e) { - ItemStack item = e.getItemInHand(); + public void onSilkChestPlace(BlockPlaceEvent event) { + ItemStack item = event.getItemInHand(); if (item.getType().isAir()) return; - Block block = e.getBlockPlaced(); + Block block = event.getBlockPlaced(); BlockState state = block.getState(); if (!(state instanceof Chest chest)) return; @@ -175,29 +154,29 @@ public class SilkChestEnchant extends ExcellentEnchant implements BlockDropEncha } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onSilkChestStore(InventoryClickEvent e) { - Inventory inventory = e.getInventory(); + public void onSilkChestStore(InventoryClickEvent event) { + Inventory inventory = event.getInventory(); if (inventory.getType() == InventoryType.CRAFTING || inventory.getType() == InventoryType.CREATIVE) return; - Player player = (Player) e.getWhoClicked(); + Player player = (Player) event.getWhoClicked(); ItemStack item; - if (e.getHotbarButton() >= 0) { - item = player.getInventory().getItem(e.getHotbarButton()); + if (event.getHotbarButton() >= 0) { + item = player.getInventory().getItem(event.getHotbarButton()); } - else item = e.getCurrentItem(); + else item = event.getCurrentItem(); if (item == null || item.getType().isAir() || !this.isSilkChest(item)) return; - Inventory clicked = e.getClickedInventory(); - if (e.getClick() != ClickType.NUMBER_KEY) { - if (clicked != null && clicked.equals(e.getView().getTopInventory())) return; + Inventory clicked = event.getClickedInventory(); + if (event.getClick() != ClickType.NUMBER_KEY) { + if (clicked != null && clicked.equals(event.getView().getTopInventory())) return; } - e.setCancelled(true); + event.setCancelled(true); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onSilkChestHopper(InventoryPickupItemEvent e) { - e.setCancelled(this.isSilkChest(e.getItem().getItemStack())); + public void onSilkChestHopper(InventoryPickupItemEvent event) { + event.setCancelled(this.isSilkChest(event.getItem().getItemStack())); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/DivineTouchEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkSpawnerEnchant.java similarity index 53% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/DivineTouchEnchant.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkSpawnerEnchant.java index 6e8270d..1ec3205 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/DivineTouchEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SilkSpawnerEnchant.java @@ -18,68 +18,80 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BlockStateMeta; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.lang.LangManager; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.Colors; -import su.nexmedia.engine.utils.LocationUtil; -import su.nexmedia.engine.utils.PDCUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.language.LangAssets; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.LocationUtil; +import su.nightexpress.nightcore.util.PDCUtil; +import su.nightexpress.nightcore.util.Plugins; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class DivineTouchEnchant extends ExcellentEnchant implements Chanced, BlockBreakEnchant, BlockDropEnchant, EventListener { +import java.io.File; - public static final String ID = "divine_touch"; +import static su.nightexpress.excellentenchants.Placeholders.*; +import static su.nightexpress.nightcore.util.text.tag.Tags.*; - private final NamespacedKey key; +public class SilkSpawnerEnchant extends AbstractEnchantmentData implements ChanceData, BlockBreakEnchant, BlockDropEnchant, SimpeListener { - private String spawnerName; - private ChanceImplementation chanceImplementation; + public static final String ID = "divine_touch"; + + private String spawnerName; + private ChanceSettingsImpl chanceSettings; private Location handleSpawner; - public DivineTouchEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.key = new NamespacedKey(plugin, "divine_spawner"); + private final NamespacedKey spawnerKey; - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to mine spawner."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(1.0); - this.getDefaults().setConflicts(SmelterEnchant.ID); + public SilkSpawnerEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.spawnerKey = new NamespacedKey(plugin, "divine_spawner"); + + this.setDescription(ENCHANTMENT_CHANCE + "% chance to mine spawner."); + this.setMaxLevel(5); + this.setRarity(Rarity.VERY_RARE); + this.setConflicts(SmelterEnchant.ID); } @Override - public void loadSettings() { - super.loadSettings(); + public boolean checkServerRequirements() { + if (Plugins.isSpigot()) { + this.warn("Enchantment can only be used in PaperMC or Paper based forks."); + return false; + } + return true; + } - this.chanceImplementation = ChanceImplementation.create(this, - "15.0 * " + Placeholders.ENCHANTMENT_LEVEL); + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.multiply(10, 1, 1, 100)); - this.spawnerName = JOption.create("Settings.Spawner_Item.Name", - Colors.GREEN + "Mob Spawner " + Colors.GRAY + "(" + Placeholders.GENERIC_TYPE + ")", + this.spawnerName = ConfigValue.create("Settings.Spawner_Item.Name", + YELLOW.enclose("Mob Spawner " + GRAY.enclose("(" + WHITE.enclose(GENERIC_TYPE) + ")")), "Spawner item display name.", - "Placeholder '" + Placeholders.GENERIC_TYPE + "' for the mob type." - ).mapReader(Colorizer::apply).read(cfg); + "Use '" + GENERIC_TYPE + "' for the mob name." + ).read(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.PICKAXE}; } @@ -89,18 +101,6 @@ public class DivineTouchEnchant extends ExcellentEnchant implements Chanced, Blo return EnchantmentTarget.TOOL; } - @NotNull - @Override - public EventPriority getDropPriority() { - return EventPriority.NORMAL; - } - - @NotNull - @Override - public EventPriority getBreakPriority() { - return EventPriority.HIGH; - } - @NotNull public ItemStack getSpawner(@NotNull CreatureSpawner spawnerBlock) { ItemStack itemSpawner = new ItemStack(Material.SPAWNER); @@ -111,10 +111,10 @@ public class DivineTouchEnchant extends ExcellentEnchant implements Chanced, Blo spawnerItem.setSpawnedType(spawnerBlock.getSpawnedType()); spawnerItem.update(true); stateItem.setBlockState(spawnerItem); - stateItem.setDisplayName(this.spawnerName.replace(Placeholders.GENERIC_TYPE, LangManager.getEntityType(spawnerBlock.getSpawnedType()))); + stateItem.setDisplayName(this.spawnerName.replace(GENERIC_TYPE, LangAssets.get(spawnerBlock.getSpawnedType()))); itemSpawner.setItemMeta(stateItem); - PDCUtil.set(itemSpawner, this.key, true); + PDCUtil.set(itemSpawner, this.spawnerKey, true); return itemSpawner; } @@ -127,7 +127,7 @@ public class DivineTouchEnchant extends ExcellentEnchant implements Chanced, Blo if (!(state instanceof CreatureSpawner spawnerBlock)) return false; - EnchantUtils.popResource(event, this.getSpawner(spawnerBlock)); + this.plugin.populateResource(event, this.getSpawner(spawnerBlock)); if (this.hasVisualEffects()) { Location location = LocationUtil.getCenter(block.getLocation()); @@ -139,7 +139,7 @@ public class DivineTouchEnchant extends ExcellentEnchant implements Chanced, Blo @Override public boolean onBreak(@NotNull BlockBreakEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { Block block = event.getBlock(); - if (!(block.getState() instanceof CreatureSpawner spawnerBlock)) return false; + if (!(block.getState() instanceof CreatureSpawner)) return false; if (!this.checkTriggerChance(level)) return false; event.setExpToDrop(0); @@ -150,14 +150,14 @@ public class DivineTouchEnchant extends ExcellentEnchant implements Chanced, Blo // Update spawner type of the placed spawner mined by Divine Touch. @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onSpawnerPlace(BlockPlaceEvent e) { - Block block = e.getBlock(); + public void onSpawnerPlace(BlockPlaceEvent event) { + Block block = event.getBlock(); if (block.getType() != Material.SPAWNER) return; - Player player = e.getPlayer(); - ItemStack spawner = player.getInventory().getItem(e.getHand()); + Player player = event.getPlayer(); + ItemStack spawner = player.getInventory().getItem(event.getHand()); if (spawner == null || spawner.getType() != Material.SPAWNER || !(spawner.getItemMeta() instanceof BlockStateMeta meta)) return; - if (PDCUtil.getBoolean(spawner, this.key).isEmpty()) return; + if (PDCUtil.getBoolean(spawner, this.spawnerKey).isEmpty()) return; CreatureSpawner spawnerItem = (CreatureSpawner) meta.getBlockState(); CreatureSpawner spawnerBlock = (CreatureSpawner) block.getState(); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SmelterEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SmelterEnchant.java index 193db0d..073ef94 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SmelterEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/SmelterEnchant.java @@ -5,80 +5,100 @@ import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.block.Container; import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; +import org.bukkit.entity.Player; import org.bukkit.event.block.BlockDropItemEvent; +import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.LocationUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.BukkitThing; +import su.nightexpress.nightcore.util.LocationUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; -import java.util.Map; +import java.io.File; +import java.util.*; -public class SmelterEnchant extends ExcellentEnchant implements Chanced, BlockDropEnchant { +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SmelterEnchant extends AbstractEnchantmentData implements ChanceData, BlockDropEnchant { public static final String ID = "smelter"; - private UniSound sound; - private Map smeltingTable; - private ChanceImplementation chanceImplementation; + private UniSound sound; + private boolean disableOnCrouch; + private ChanceSettingsImpl chanceSettings; - public SmelterEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to smelt a block/ore."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.3); - this.getDefaults().setConflicts( - DivineTouchEnchant.ID, + private final Set exemptedBlocks; + private final Set recipes; + + public SmelterEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Smelts mined blocks with " + ENCHANTMENT_CHANCE + "% chance."); + this.setMaxLevel(5); + this.setRarity(Rarity.UNCOMMON); + this.setConflicts( + SilkSpawnerEnchant.ID, Enchantment.SILK_TOUCH.getKey().getKey() ); + + this.exemptedBlocks = new HashSet<>(); + this.recipes = new HashSet<>(); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 10"); + protected void loadAdditional(@NotNull FileConfig config) { + this.plugin.getServer().recipeIterator().forEachRemaining(recipe -> { + if (recipe instanceof FurnaceRecipe furnaceRecipe && furnaceRecipe.getInput().getType().isBlock()) { + this.recipes.add(furnaceRecipe); + } + }); - this.sound = JOption.create("Settings.Sound",UniSound.of(Sound.BLOCK_LAVA_EXTINGUISH), + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(10, 8, 1, 100)); + + this.disableOnCrouch = ConfigValue.create("Settings.Disable_On_Crouch", + true, + "Sets whether or not enchantment will have no effect when crouching." + ).read(config); + + this.sound = ConfigValue.create("Settings.Sound", + UniSound.of(Sound.BLOCK_LAVA_EXTINGUISH), "Sound to play on smelting.", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html").read(cfg); + "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html" + ).read(config); - this.smeltingTable = JOption.forMap("Settings.Smelting_Table", - key -> Material.getMaterial(key.toUpperCase()), - (cfg, path, key) -> Material.getMaterial(cfg.getString(path + "." + key, "").toUpperCase()), - Map.of( - Material.RAW_IRON, Material.IRON_INGOT, - Material.RAW_GOLD, Material.GOLD_INGOT - ), - "Table of Original -> Smelted items.", - "Syntax: 'Material Source : Material Result'.", - "Note: Material source is material name of the dropped item, not the broken block!", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html" - ).setWriter((cfg, path, map) -> map.forEach((src, to) -> cfg.set(path + "." + src.name(), to.name()))).read(cfg); + this.exemptedBlocks.addAll(ConfigValue.forSet("Settings.Exempted_Blocks", + BukkitThing::getMaterial, + (cfg, path, set) -> cfg.set(path, set.stream().map(material -> material.getKey().getKey()).toList()), + Set.of(Material.STONE), + "List of blocks that are immune to smelter effect." + ).read(config)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.PICKAXE, ItemCategory.AXE, ItemCategory.SHOVEL}; } @@ -88,28 +108,26 @@ public class SmelterEnchant extends ExcellentEnchant implements Chanced, BlockDr return EnchantmentTarget.TOOL; } - @NotNull @Override - public EventPriority getDropPriority() { - return EventPriority.NORMAL; - } + public boolean onDrop(@NotNull BlockDropItemEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level) { + if (this.disableOnCrouch && entity instanceof Player player && player.isSneaking()) return false; - @Override - public boolean onDrop(@NotNull BlockDropItemEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { - // TODO Use furnace recipes & Re-add smelted items instead of setType + BlockState state = event.getBlockState(); + if (state instanceof Container || this.exemptedBlocks.contains(state.getType())) return false; - if (event.getBlockState() instanceof Container) return false; if (!this.checkTriggerChance(level)) return false; - if (event.getItems().stream().noneMatch(drop -> this.isSmeltable(drop.getItemStack().getType()))) return false; - event.getItems().forEach(drop -> { - Material material = this.smeltingTable.get(drop.getItemStack().getType()); - if (material != null) { - ItemStack stack = drop.getItemStack(); - stack.setType(material); - drop.setItemStack(stack); - } + List smelts = new ArrayList<>(); + event.getItems().removeIf(drop -> { + FurnaceRecipe recipe = this.recipes.stream().filter(rec -> rec.getInputChoice().test(drop.getItemStack())).findFirst().orElse(null); + if (recipe == null) return false; + + smelts.add(recipe.getResult()); + return true; }); + if (smelts.isEmpty()) return false; + + smelts.forEach(itemStack -> this.plugin.populateResource(event, itemStack)); Block block = event.getBlockState().getBlock(); if (this.hasVisualEffects()) { @@ -119,8 +137,4 @@ public class SmelterEnchant extends ExcellentEnchant implements Chanced, BlockDr } return true; } - - public boolean isSmeltable(@NotNull Material material) { - return this.smeltingTable.containsKey(material); - } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TelekinesisEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TelekinesisEnchant.java index b89452a..4996510 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TelekinesisEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TelekinesisEnchant.java @@ -7,42 +7,47 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockDropItemEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.PlayerUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.Players; -public class TelekinesisEnchant extends ExcellentEnchant implements Chanced, BlockDropEnchant { +import java.io.File; + + +public class TelekinesisEnchant extends AbstractEnchantmentData implements ChanceData, BlockDropEnchant { public static final String ID = "telekinesis"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public TelekinesisEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Moves all blocks loot directly to your inventory."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.75); + public TelekinesisEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Moves all blocks loot directly to your inventory."); + this.setMaxLevel(1); + this.setRarity(Rarity.VERY_RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.TOOL}; } @@ -64,7 +69,7 @@ public class TelekinesisEnchant extends ExcellentEnchant implements Chanced, Blo if (!this.checkTriggerChance(level)) return false; event.getItems().forEach(drop -> { - PlayerUtil.addItem(player, drop.getItemStack()); + Players.addItem(player, drop.getItemStack()); }); event.getItems().clear(); return true; diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TreasuresEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TreasuresEnchant.java deleted file mode 100644 index f8f2269..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TreasuresEnchant.java +++ /dev/null @@ -1,167 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.tool; - -import org.bukkit.Material; -import org.bukkit.Tag; -import org.bukkit.block.Block; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockDropItemEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.blocktracker.PlayerBlockTracker; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.Cleanable; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; - -import java.util.*; -import java.util.function.Predicate; - -public class TreasuresEnchant extends ExcellentEnchant implements Chanced, BlockBreakEnchant, BlockDropEnchant, Cleanable { - - public static final String ID = "treasures"; - - private final Predicate blockTracker; - - private Map> treasures; - private ChanceImplementation chanceImplementation; - - private Block handleDrop; - - public TreasuresEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to attempt to find a treasure in mined block."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.1); - - PlayerBlockTracker.initialize(); - PlayerBlockTracker.BLOCK_FILTERS.add(this.blockTracker = (block) -> { - return this.treasures.containsKey(block.getType()); - }); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 4.0"); - - this.treasures = new HashMap<>(); - - if (cfg.getSection("Settings.Treasures").isEmpty()) { - Tag.BASE_STONE_OVERWORLD.getValues().forEach(material -> { - cfg.addMissing("Settings.Treasures." + material.name() + ".BONE_MEAL", 2.0); - }); - Tag.DIRT.getValues().forEach(material -> { - cfg.addMissing("Settings.Treasures." + material.name() + ".CLAY_BALL", 0.5); - cfg.addMissing("Settings.Treasures." + material.name() + ".BOWL", 1.0); - cfg.addMissing("Settings.Treasures." + material.name() + ".STICK", 2.0); - }); - Tag.SAND.getValues().forEach(material -> { - cfg.addMissing("Settings.Treasures." + material.name() + ".GLOWSTONE_DUST", 1.0); - cfg.addMissing("Settings.Treasures." + material.name() + ".GOLD_NUGGET", 0.3); - }); - Tag.LEAVES.getValues().forEach(material -> { - cfg.addMissing("Settings.Treasures." + material.name() + ".APPLE", 12.0); - }); - } - - for (String sFromArray : cfg.getSection("Settings.Treasures")) { - for (String sFrom : sFromArray.split(",")) { - Material mFrom = Material.getMaterial(sFrom.toUpperCase()); - if (mFrom == null) { - plugin.error("[Treasures] Invalid source material '" + sFrom + "' !"); - continue; - } - Map treasuresList = new HashMap<>(); - - for (String sTo : cfg.getSection("Settings.Treasures." + sFromArray)) { - Material mTo = Material.getMaterial(sTo.toUpperCase()); - if (mTo == null) { - plugin.error("[Treasures] Invalid result material '" + sTo + "' for '" + sFromArray + "' !"); - continue; - } - - double tChance = cfg.getDouble("Settings.Treasures." + sFromArray + "." + sTo); - treasuresList.put(mTo, tChance); - } - this.treasures.put(mFrom, treasuresList); - } - } - - this.cfg.setComments("Settings.Treasures", - "List of source materials (blocks that will drop additional loot). Separated by a comma.", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html"); - } - - @Override - public void clear() { - PlayerBlockTracker.BLOCK_FILTERS.remove(this.blockTracker); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @Override - @NotNull - public ItemCategory[] getFitItemTypes() { - return new ItemCategory[]{ItemCategory.PICKAXE, ItemCategory.AXE, ItemCategory.SHOVEL}; - } - - @Override - @NotNull - public EnchantmentTarget getCategory() { - return EnchantmentTarget.TOOL; - } - - @NotNull - @Override - public EventPriority getDropPriority() { - return EventPriority.NORMAL; - } - - @Override - public boolean onBreak(@NotNull BlockBreakEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { - if (!event.isDropItems()) return false; - if (PlayerBlockTracker.isTracked(event.getBlock())) return false; - - this.handleDrop = event.getBlock(); - return false; - } - - @Override - public boolean onDrop(@NotNull BlockDropItemEvent event, @NotNull LivingEntity player, @NotNull ItemStack item, int level) { - if (this.handleDrop != event.getBlock()) return false; - this.handleDrop = null; - - if (!this.checkTriggerChance(level)) return false; - - this.getTreasures(event.getBlockState().getType()).forEach(treasure -> { - EnchantUtils.popResource(event, treasure); - }); - return true; - } - - @NotNull - public final List getTreasures(@NotNull Material type) { - List list = new ArrayList<>(); - Map treasures = this.treasures.getOrDefault(type, Collections.emptyMap()); - treasures.forEach((mat, chance) -> { - if (mat.isAir() || !mat.isItem() || !Rnd.chance(chance)) return; - list.add(new ItemStack(mat)); - }); - return list; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TunnelEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TunnelEnchant.java index a0e43b5..23fb579 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TunnelEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/TunnelEnchant.java @@ -9,19 +9,22 @@ import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import java.io.File; import java.util.HashSet; import java.util.List; import java.util.Set; -public class TunnelEnchant extends ExcellentEnchant implements BlockBreakEnchant { +public class TunnelEnchant extends AbstractEnchantmentData implements BlockBreakEnchant { public static final String ID = "tunnel"; // X and Z offsets for each block AoE mined @@ -35,25 +38,25 @@ public class TunnelEnchant extends ExcellentEnchant implements BlockBreakEnchant private boolean disableOnSneak; - public TunnelEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); + public TunnelEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); - this.getDefaults().setDescription("Mines multiple blocks at once in a certain shape."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(1.0); - this.getDefaults().setConflicts(VeinminerEnchant.ID, BlastMiningEnchant.ID); + this.setDescription("Mines multiple blocks at once in a certain shape."); + this.setMaxLevel(3); + this.setRarity(Rarity.VERY_RARE); + this.setConflicts(VeinminerEnchant.ID, BlastMiningEnchant.ID); } @Override - public void loadSettings() { - super.loadSettings(); - this.disableOnSneak = JOption.create("Settings.Ignore_When_Sneaking", true, - "When 'true' the enchantment won't be triggered when sneaking.").read(cfg); + protected void loadAdditional(@NotNull FileConfig config) { + this.disableOnSneak = ConfigValue.create("Settings.Disable_On_Crouch", + true, + "Sets whether or not enchantment will have no effect when crouching.").read(config); } @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.PICKAXE, ItemCategory.SHOVEL}; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/VeinminerEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/VeinminerEnchant.java index 731a750..088df42 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/VeinminerEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/tool/VeinminerEnchant.java @@ -10,54 +10,62 @@ import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; import su.nightexpress.excellentenchants.api.enchantment.ItemCategory; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.BukkitThing; +import java.io.File; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -public class VeinminerEnchant extends ExcellentEnchant implements BlockBreakEnchant { +import static su.nightexpress.excellentenchants.Placeholders.*; - public static final String ID = "veinminer"; +public class VeinminerEnchant extends AbstractEnchantmentData implements BlockBreakEnchant { + + public static final String ID = "veinminer"; private static final BlockFace[] AREA = { BlockFace.UP, BlockFace.DOWN, BlockFace.EAST, BlockFace.WEST, BlockFace.SOUTH, BlockFace.NORTH }; - private static final String PLACEHOLDER_BLOCK_LIMIT = "%enchantment_block_limit%"; + private Modifier blocksLimit; + private Set affectedBlocks; + private boolean disableOnCrouch; - private EnchantScaler blocksLimit; - private Set blocksAffected; + public VeinminerEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); - public VeinminerEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - - this.getDefaults().setDescription("Mines up to " + PLACEHOLDER_BLOCK_LIMIT + " blocks of the ore vein at once."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - this.getDefaults().setConflicts(BlastMiningEnchant.ID, TunnelEnchant.ID); + this.setDescription("Mines up to " + GENERIC_AMOUNT + " blocks of the ore vein at once."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + this.setConflicts(BlastMiningEnchant.ID, TunnelEnchant.ID); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.disableOnCrouch = ConfigValue.create("Settings.Disable_On_Crouch", + true, + "Sets whether or not enchantment will have no effect when crouching." + ).read(config); - this.blocksLimit = EnchantScaler.read(this, "Settings.Blocks.Max_At_Once", - "6 + " + Placeholders.ENCHANTMENT_LEVEL, - "How much amount of blocks can be destroted at single use?"); + this.blocksLimit = Modifier.read(config, "Settings.Blocks.Limit", + Modifier.add(4, 1, 1, 16), + "Max. possible amount of blocks to be mined at the same time."); - this.blocksAffected = JOption.forSet("Settings.Blocks.Affected", - str -> Material.getMaterial(str.toUpperCase()), + this.affectedBlocks = ConfigValue.forSet("Settings.Blocks.List", + BukkitThing::getMaterial, + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), () -> { Set set = new HashSet<>(); set.addAll(Tag.COAL_ORES.getValues()); @@ -72,16 +80,15 @@ public class VeinminerEnchant extends ExcellentEnchant implements BlockBreakEnch set.add(Material.NETHER_QUARTZ_ORE); return set; }, - "List of blocks, that will be affected by this enchantment.", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html" - ).setWriter((cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList())).read(cfg); + "List of blocks affected by this enchantment." + ).read(config); - this.addPlaceholder(PLACEHOLDER_BLOCK_LIMIT, level -> String.valueOf(this.getBlocksLimit(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> String.valueOf(this.getBlocksLimit(level))); } @NotNull - public Set getBlocksAffected() { - return this.blocksAffected; + public Set getAffectedBlocks() { + return this.affectedBlocks; } public int getBlocksLimit(int level) { @@ -90,7 +97,7 @@ public class VeinminerEnchant extends ExcellentEnchant implements BlockBreakEnch @Override @NotNull - public ItemCategory[] getFitItemTypes() { + public ItemCategory[] getItemCategories() { return new ItemCategory[]{ItemCategory.PICKAXE}; } @@ -127,10 +134,11 @@ public class VeinminerEnchant extends ExcellentEnchant implements BlockBreakEnch public boolean onBreak(@NotNull BlockBreakEvent event, @NotNull LivingEntity entity, @NotNull ItemStack tool, int level) { if (!(entity instanceof Player player)) return false; if (EnchantUtils.isBusy()) return false; + if (this.disableOnCrouch && player.isSneaking()) return false; Block block = event.getBlock(); if (block.getDrops(tool, player).isEmpty()) return false; - if (!this.getBlocksAffected().contains(block.getType())) return false; + if (!this.getAffectedBlocks().contains(block.getType())) return false; NoCheatPlusHook.exemptBlocks(player); this.vein(player, block, level); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/CurseOfFragilityEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/CurseOfFragilityEnchant.java index 1a09985..0e57f13 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/CurseOfFragilityEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/CurseOfFragilityEnchant.java @@ -11,21 +11,30 @@ import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; -public class CurseOfFragilityEnchant extends ExcellentEnchant implements GenericEnchant, EventListener { +import java.io.File; + +public class CurseOfFragilityEnchant extends AbstractEnchantmentData implements GenericEnchant, SimpeListener { public static final String ID = "curse_of_fragility"; - public CurseOfFragilityEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Prevents an item from being grindstoned or anviled."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0D); + public CurseOfFragilityEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Prevents an item from being grindstoned or anviled."); + this.setMaxLevel(1); + this.setRarity(Rarity.COMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + } @NotNull @@ -34,43 +43,48 @@ public class CurseOfFragilityEnchant extends ExcellentEnchant implements Generic return EnchantmentTarget.BREAKABLE; } + @Override + public boolean isCurse() { + return true; + } + @EventHandler(priority = EventPriority.HIGHEST) - public void onItemAnvil(PrepareAnvilEvent e) { - AnvilInventory inventory = e.getInventory(); + public void onItemAnvil(PrepareAnvilEvent event) { + AnvilInventory inventory = event.getInventory(); ItemStack first = inventory.getItem(0); ItemStack second = inventory.getItem(1); - boolean cursedFirst = (first != null && EnchantUtils.getLevel(first, this.getBackend()) >= 1); - boolean cursedSecond = (second != null && EnchantUtils.getLevel(second, this.getBackend()) >= 1); + boolean cursedFirst = (first != null && EnchantUtils.getLevel(first, this.getEnchantment()) >= 1); + boolean cursedSecond = (second != null && EnchantUtils.getLevel(second, this.getEnchantment()) >= 1); if (cursedFirst || cursedSecond) { - e.setResult(null); + event.setResult(null); } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onItemGrindstoneClick(InventoryClickEvent e) { - Inventory inventory = e.getInventory(); + public void onItemGrindstoneClick(InventoryClickEvent event) { + Inventory inventory = event.getInventory(); if (inventory.getType() != InventoryType.GRINDSTONE) return; this.stopGrindstone(inventory); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onItemGrindstoneDrag(InventoryDragEvent e) { - Inventory inventory = e.getInventory(); + public void onItemGrindstoneDrag(InventoryDragEvent event) { + Inventory inventory = event.getInventory(); if (inventory.getType() != InventoryType.GRINDSTONE) return; this.stopGrindstone(inventory); } private void stopGrindstone(@NotNull Inventory inventory) { - plugin.getScheduler().runTask(plugin, () -> { + plugin.runTask(task -> { ItemStack first = inventory.getItem(0); ItemStack second = inventory.getItem(1); - boolean cursedFirst = (first != null && EnchantUtils.getLevel(first, this.getBackend()) >= 1); - boolean cursedSecond = (second != null && EnchantUtils.getLevel(second, this.getBackend()) >= 1); + boolean cursedFirst = (first != null && EnchantUtils.getLevel(first, this.getEnchantment()) >= 1); + boolean cursedSecond = (second != null && EnchantUtils.getLevel(second, this.getEnchantment()) >= 1); if (cursedFirst || cursedSecond) { inventory.setItem(2, null); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/RestoreEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/RestoreEnchant.java index 7abd1cd..d3a647a 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/RestoreEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/RestoreEnchant.java @@ -8,51 +8,53 @@ import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class RestoreEnchant extends ExcellentEnchant implements GenericEnchant, Chanced, EventListener { +import java.io.File; - public static final String ID = "restore"; - public static final String PLACEHOLDER_DURABILITY_RESTORE = "%durability_restore%"; +import static su.nightexpress.excellentenchants.Placeholders.*; - private ChanceImplementation chanceImplementation; - private EnchantScaler durabilityRestore; +public class RestoreEnchant extends AbstractEnchantmentData implements GenericEnchant, ChanceData, SimpeListener { - public RestoreEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to save item from breaking back to " + PLACEHOLDER_DURABILITY_RESTORE + "%"); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.6); + public static final String ID = "restore"; + + private ChanceSettingsImpl chanceSettings; + private Modifier durabilityRestore; + + public RestoreEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to save item from breaking back to " + GENERIC_AMOUNT + "%"); + this.setMaxLevel(5); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(20, 6, 1, 100)); - this.chanceImplementation = ChanceImplementation.create(this, - "35.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 8"); - - this.durabilityRestore = EnchantScaler.read(this, "Settings.Durability_Restoration", - "25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5", + this.durabilityRestore = Modifier.read(config, "Settings.Durability_Restoration", + Modifier.add(25, 5, 1, 100), "Amount of durability (in percent of item max) to be restored."); - this.addPlaceholder(PLACEHOLDER_DURABILITY_RESTORE, level -> NumberUtil.format(this.getDurabilityRestore(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getDurabilityRestore(level))); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @@ -74,7 +76,7 @@ public class RestoreEnchant extends ExcellentEnchant implements GenericEnchant, int maxDurability = item.getType().getMaxDurability(); if (damageable.getDamage() + damage < maxDurability) return; - int level = EnchantUtils.getLevel(item, this.getBackend()); + int level = EnchantUtils.getLevel(item, this.getEnchantment()); if (level <= 0) return; if (this.isOutOfCharges(item)) return; @@ -88,7 +90,7 @@ public class RestoreEnchant extends ExcellentEnchant implements GenericEnchant, damageable.setDamage(restored); item.setItemMeta(damageable); - EnchantUtils.remove(item, this.getBackend()); + EnchantUtils.remove(item, this.getEnchantment()); if (this.hasVisualEffects()) { UniSound.of(Sound.ITEM_TOTEM_USE).play(event.getPlayer()); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/SoulboundEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/SoulboundEnchant.java index 4ad31fa..f030917 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/SoulboundEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/universal/SoulboundEnchant.java @@ -9,25 +9,33 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nightexpress.excellentenchants.ExcellentEnchants; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import java.io.File; import java.util.ArrayList; import java.util.List; -public class SoulboundEnchant extends ExcellentEnchant implements GenericEnchant, EventListener { +public class SoulboundEnchant extends AbstractEnchantmentData implements GenericEnchant, SimpeListener { public static final String ID = "soulbound"; - public SoulboundEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Protects from being dropped on death."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.8); - this.getDefaults().setConflicts(Enchantment.VANISHING_CURSE.getKey().getKey()); + public SoulboundEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Protects from being dropped on death."); + this.setMaxLevel(1); + this.setRarity(Rarity.VERY_RARE); + this.setConflicts(Enchantment.VANISHING_CURSE.getKey().getKey()); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + } @NotNull @@ -47,7 +55,7 @@ public class SoulboundEnchant extends ExcellentEnchant implements GenericEnchant World world = player.getWorld(); deathEvent.getDrops().removeIf(drop -> { - if (EnchantUtils.getLevel(drop, this.getBackend()) > 0) { + if (EnchantUtils.getLevel(drop, this.getEnchantment()) > 0) { if (this.isOutOfCharges(drop)) return false; saveList.add(drop); @@ -64,7 +72,7 @@ public class SoulboundEnchant extends ExcellentEnchant implements GenericEnchant world.dropItemNaturally(location, save); } else { - this.consumeChargesNoUpdate(save, EnchantUtils.getLevel(save, this.getBackend())); + this.consumeChargesNoUpdate(save, EnchantUtils.getLevel(save, this.getEnchantment())); player.getInventory().addItem(save); } }); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantBaneOfNetherspawn.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/BaneOfNetherspawnEnchant.java similarity index 54% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantBaneOfNetherspawn.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/BaneOfNetherspawnEnchant.java index 9dbbadc..6ed1302 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantBaneOfNetherspawn.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/BaneOfNetherspawnEnchant.java @@ -7,23 +7,27 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.Lists; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import java.io.File; import java.util.Set; -public class EnchantBaneOfNetherspawn extends ExcellentEnchant implements CombatEnchant { +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class BaneOfNetherspawnEnchant extends AbstractEnchantmentData implements CombatEnchant { public static final String ID = "bane_of_netherspawn"; - private static final String PLACEHOLDER_DAMAGE = "%enchantment_damage%"; - private static final Set ENTITY_TYPES = Set.of( + private static final Set ENTITY_TYPES = Lists.newSet( EntityType.BLAZE, EntityType.MAGMA_CUBE, EntityType.WITHER_SKELETON, EntityType.GHAST, EntityType.WITHER, EntityType.PIGLIN, EntityType.PIGLIN_BRUTE, @@ -31,26 +35,27 @@ public class EnchantBaneOfNetherspawn extends ExcellentEnchant implements Combat EntityType.STRIDER, EntityType.ZOMBIFIED_PIGLIN ); - private boolean damageModifier; - private EnchantScaler damageFormula; + private boolean damageModifier; + private Modifier damageFormula; - public EnchantBaneOfNetherspawn(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Inflicts " + PLACEHOLDER_DAMAGE + " more damage to nether mobs."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.1); + public BaneOfNetherspawnEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Inflicts " + GENERIC_DAMAGE + "❤ more damage to nether mobs."); + this.setMaxLevel(5); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.damageModifier = JOption.create("Settings.Damage.As_Modifier", false, - "When 'true' multiplies the damage. When 'false' sums plain values.").read(cfg); - this.damageFormula = EnchantScaler.read(this, "Settings.Damage.Amount", - "0.5 * " + Placeholders.ENCHANTMENT_LEVEL, + protected void loadAdditional(@NotNull FileConfig config) { + this.damageModifier = ConfigValue.create("Settings.Damage.As_Modifier", + false, + "When 'true' multiplies the damage. When 'false' sums plain values.").read(config); + + this.damageFormula = Modifier.read(config, "Settings.Damage.Amount", + Modifier.add(0.75, 0.25, 1, 10000), "Amount of additional damage."); - this.addPlaceholder(PLACEHOLDER_DAMAGE, level -> NumberUtil.format(this.getDamageModifier(level))); + this.addPlaceholder(GENERIC_DAMAGE, level -> NumberUtil.format(this.getDamageModifier(level))); } public double getDamageModifier(int level) { @@ -70,9 +75,12 @@ public class EnchantBaneOfNetherspawn extends ExcellentEnchant implements Combat double damageEvent = event.getDamage(); double damageAdd = this.getDamageModifier(level); event.setDamage(this.damageModifier ? damageEvent * damageAdd : damageEvent + damageAdd); + if (this.hasVisualEffects()) { - UniParticle.of(Particle.SMOKE_NORMAL).play(victim.getEyeLocation(), 0.25, 0.1, 30); + UniParticle.of(Particle.SMOKE_NORMAL).play(victim.getEyeLocation(), 0.25, 0.1, 25); + UniParticle.of(Particle.LAVA).play(victim.getEyeLocation(), 0.25, 0.1, 5); } + return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/BlindnessEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/BlindnessEnchant.java new file mode 100644 index 0000000..2533cf5 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/BlindnessEnchant.java @@ -0,0 +1,92 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class BlindnessEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "blindness"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public BlindnessEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(7, 3, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.BLINDNESS, false, + Modifier.add(4, 1, 1, 300), + Modifier.add(0, 1, 1, 10)); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.of(Particle.SMOKE_NORMAL).play(victim.getEyeLocation(), 0.25, 0.1, 30); + } + + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ConfusionEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ConfusionEnchant.java new file mode 100644 index 0000000..58d78a2 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ConfusionEnchant.java @@ -0,0 +1,92 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Material; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ConfusionEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "confusion"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public ConfusionEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(15, 5, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.CONFUSION, false, + Modifier.add(7, 1, 1, 300), + Modifier.add(0, 1, 1, 10)); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.itemCrack(Material.ROTTEN_FLESH).play(victim.getEyeLocation(), 0.25, 0.1, 30); + } + + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantCure.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CureEnchant.java similarity index 59% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantCure.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CureEnchant.java index c4b9b8f..46df881 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantCure.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CureEnchant.java @@ -8,42 +8,46 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import java.io.File; import java.util.Set; -public class EnchantCure extends ExcellentEnchant implements Chanced, CombatEnchant { +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class CureEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "cure"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; private static final Set CUREABLE = Sets.newHashSet(EntityType.ZOMBIFIED_PIGLIN, EntityType.ZOMBIE_VILLAGER); - public EnchantCure(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to cure Zombified Piglins and Zombie Villagers on hit."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.5); + public CureEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to cure Zombified Piglins and Zombie Villagers on hit."); + this.setMaxLevel(5); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 8"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(4, 2.2, 1, 100)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override @@ -70,7 +74,7 @@ public class EnchantCure extends ExcellentEnchant implements Chanced, CombatEnch UniParticle.of(Particle.CLOUD).play(victim.getEyeLocation(), 0.25, 0.1, 30); } - if (victim instanceof PigZombie pigZombie) { + if (victim instanceof PigZombie) { victim.getWorld().spawn(victim.getLocation(), Piglin.class); victim.remove(); } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CurseOfDeathEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CurseOfDeathEnchant.java index c789f24..8abd82d 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CurseOfDeathEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CurseOfDeathEnchant.java @@ -7,31 +7,34 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; -public class CurseOfDeathEnchant extends ExcellentEnchant implements DeathEnchant, Chanced { +import java.io.File; + +public class CurseOfDeathEnchant extends AbstractEnchantmentData implements DeathEnchant, ChanceData { public static final String ID = "curse_of_death"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public CurseOfDeathEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("When killing players, you have a chance of dying too."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0D); + public CurseOfDeathEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("When killing players, you have a chance of dying too."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - - this.chanceImplementation = ChanceImplementation.create(this, Placeholders.ENCHANTMENT_LEVEL + " * 0.1"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(0.5, 0.15, 1, 100)); } @NotNull @@ -42,8 +45,8 @@ public class CurseOfDeathEnchant extends ExcellentEnchant implements DeathEnchan @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } @Override @@ -63,7 +66,7 @@ public class CurseOfDeathEnchant extends ExcellentEnchant implements DeathEnchan @Override public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, ItemStack weapon, int level) { - if (!(entity instanceof Player dead)) return false; + if (!(entity instanceof Player)) return false; if (!this.checkTriggerChance(level)) return false; killer.setHealth(0D); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantCutter.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CutterEnchant.java similarity index 57% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantCutter.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CutterEnchant.java index eaf9d66..2a7c8e7 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantCutter.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/CutterEnchant.java @@ -12,58 +12,64 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.random.Rnd; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.random.Rnd; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class EnchantCutter extends ExcellentEnchant implements Chanced, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class CutterEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "cutter"; - private static final String PLACEHOLDER_DURABILITY_DAMAGE = "%enchantment_durability_damage%"; - private EnchantScaler durabilityReduction; - private ChanceImplementation chanceImplementation; - private boolean allowPlayers; - private boolean allowMobs; + private Modifier durabilityReduction; + private ChanceSettingsImpl chanceSettings; + private boolean allowPlayers; + private boolean allowMobs; - public EnchantCutter(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to throw away enemy''s armor and damage it for " + PLACEHOLDER_DURABILITY_DAMAGE + "%."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.75); + public CutterEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to throw away enemy''s armor and damage it for " + GENERIC_DAMAGE + "%."); + this.setMaxLevel(5); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "1.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.6"); - this.durabilityReduction = EnchantScaler.read(this, "Settings.Item.Durability_Reduction", - Placeholders.ENCHANTMENT_LEVEL + " / 100", + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(1, 0.5, 1, 100)); + + this.durabilityReduction = Modifier.read(config, "Settings.Item.Durability_Reduction", + Modifier.add(0, 0.01, 1, 1D), "Amount (in percent) of how much item durability will be reduced."); - this.allowPlayers = JOption.create("Settings.Allow_Players", true, - "Sets whether or not this enchantment will have effect on players.").read(cfg); + this.allowPlayers = ConfigValue.create("Settings.Allow_Players", + true, + "Sets whether or not this enchantment will have effect on players.").read(config); - this.allowMobs = JOption.create("Settings.Allow_Mobs", true, - "Sets whether or not this enchantment will have effect on mobs.").read(cfg); + this.allowMobs = ConfigValue.create("Settings.Allow_Mobs", + true, + "Sets whether or not this enchantment will have effect on mobs.").read(config); - this.addPlaceholder(PLACEHOLDER_DURABILITY_DAMAGE, level -> NumberUtil.format(this.getDurabilityReduction(level) * 100D)); + this.addPlaceholder(GENERIC_DAMAGE, level -> NumberUtil.format(this.getDurabilityReduction(level) * 100D)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public final double getDurabilityReduction(int level) { @@ -116,6 +122,7 @@ public class EnchantCutter extends ExcellentEnchant implements Chanced, CombatEn UniParticle.itemCrack(itemCut).play(victim.getEyeLocation(), 0.25, 0.15, 30); UniSound.of(Sound.ENTITY_ITEM_BREAK).play(victim.getLocation()); } + return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDoubleStrike.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/DoubleStrikeEnchant.java similarity index 52% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDoubleStrike.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/DoubleStrikeEnchant.java index 2d4f59b..12c1953 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDoubleStrike.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/DoubleStrikeEnchant.java @@ -8,39 +8,44 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class EnchantDoubleStrike extends ExcellentEnchant implements Chanced, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class DoubleStrikeEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "double_strike"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public EnchantDoubleStrike(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to inflict double damage."); - this.getDefaults().setLevelMax(4); - this.getDefaults().setTier(1.0); + public DoubleStrikeEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to inflict double damage."); + this.setMaxLevel(4); + this.setRarity(Rarity.VERY_RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "4.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.8"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(2, 0.5, 1, 100D)); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantBlindness.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantBlindness.java deleted file mode 100644 index 7f3d4cf..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantBlindness.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantBlindness extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "blindness"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantBlindness(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "15.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 3"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.BLINDNESS, false, - "3.5 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.of(Particle.SMOKE_NORMAL).play(victim.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantConfusion.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantConfusion.java deleted file mode 100644 index 50c5452..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantConfusion.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Material; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantConfusion extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "confusion"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantConfusion(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "15.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.CONFUSION, false, - "5.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 1.5", - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.itemCrack(Material.ROTTEN_FLESH).play(victim.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDecapitator.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDecapitator.java index e275682..314dfa1 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDecapitator.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantDecapitator.java @@ -17,66 +17,72 @@ import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.lang.LangManager; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.ItemUtil; -import su.nexmedia.engine.utils.PDCUtil; -import su.nexmedia.engine.utils.StringUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.language.LangAssets; +import su.nightexpress.nightcore.util.ItemUtil; +import su.nightexpress.nightcore.util.PDCUtil; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Set; -public class EnchantDecapitator extends ExcellentEnchant implements Chanced, DeathEnchant { +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class EnchantDecapitator extends AbstractEnchantmentData implements ChanceData, DeathEnchant { public static final String ID = "decapitator"; - private Set ignoredEntityTypes; - private String headName; + private Set ignoredEntityTypes; + private String headName; private Map headTextures; - - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; private final NamespacedKey skullKey; - public EnchantDecapitator(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to obtain player''s or mob''s head."); - this.getDefaults().setLevelMax(4); - this.getDefaults().setTier(0.75); + public EnchantDecapitator(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to obtain player''s or mob''s head."); + this.setMaxLevel(4); + this.setRarity(Rarity.RARE); this.skullKey = new NamespacedKey(plugin, this.getId() + ".entity_type"); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "5.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 1.75"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(5, 1.75, 1, 100)); - this.ignoredEntityTypes = JOption.forSet("Settings.Ignored_Entity_Types", + this.ignoredEntityTypes = ConfigValue.forSet("Settings.Ignored_Entity_Types", str -> StringUtil.getEnum(str, EntityType.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), () -> Set.of( EntityType.BAT, EntityType.BEE, EntityType.ENDER_DRAGON, EntityType.WITHER, EntityType.WITHER_SKELETON ), "List of entities, that won't drop heads." - ).setWriter((cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList())).read(cfg); + ).read(config); - this.headName = JOption.create("Settings.Head_Item.Name", "&c" + Placeholders.GENERIC_TYPE + "'s Head", - "Head item display name. Use '" + Placeholders.GENERIC_TYPE + "' for entity name.") - .mapReader(Colorizer::apply).read(cfg); + this.headName = ConfigValue.create("Settings.Head_Item.Name", + "&c" + GENERIC_TYPE + "'s Head", + "Head item display name. Use '" + GENERIC_TYPE + "' for entity name.") + .read(config); - this.headTextures = JOption.forMap("Settings.Head_Item.Textures", + // TODO + this.headTextures = ConfigValue.forMap("Settings.Head_Item.Textures", id -> StringUtil.getEnum(id, EntityType.class).orElse(null), - (cfg, path, id) -> cfg.getString(path + "." + id), + (cfg2, path, id) -> cfg2.getString(path + "." + id), + (cfg2, path, map) -> map.forEach((type, txt) -> cfg2.set(path + "." + type.name(), txt)), () -> { Map map = new HashMap<>(); map.put(EntityType.AXOLOTL, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNThkYTFhMGEyYTEzZGQyMDliZmMyNTI5ZDljN2MyOWEyOWRkOWEyM2ZmNGI4MGIzOGI4OTk2MTc3MmU4MDM5ZSJ9fX0="); @@ -148,28 +154,13 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea "Head texture values for each entity type.", "You can take some from http://minecraft-heads.com", "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html" - ).setWriter((cfg, path, map) -> map.forEach((type, txt) -> cfg.set(path + "." + type.name(), txt))).read(cfg); - - /*for (String sType : cfg.getSection("Settings.Head_Item.Textures")) { - this.headTextures.put(sType.toUpperCase(), cfg.getString("Settings.Head_Item.Textures." + sType, "")); - } - this.cfg.setComments("Settings.Head_Item.Textures", - "Head texture values for each entity type.", - "You can take some from http://minecraft-heads.com", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html"); - - this.headTextures = new JOption>("Settings.Head_Item.Textures", - (cfg, path, def) -> cfg.getSection(path).stream().collect(Collectors.toMap(String::toUpperCase, v -> cfg.getString(path + "." + v, ""))), - HashMap::new, - "Head texture values for each entity type.", - "You can take some from http://minecraft-heads.com", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html").read(cfg);*/ + ).read(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @Override @@ -217,14 +208,14 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea String entityName; if (entity instanceof Player player) { - entityName = this.headName.replace(Placeholders.GENERIC_TYPE, entity.getName()); + entityName = this.headName.replace(GENERIC_TYPE, entity.getName()); meta.setOwningPlayer(player); } else { String texture = this.headTextures.get(entity.getType()); if (texture == null) return false; - entityName = this.headName.replace(Placeholders.GENERIC_TYPE, LangManager.getEntityType(entity.getType())); + entityName = this.headName.replace(GENERIC_TYPE, LangAssets.get(entity.getType())); ItemUtil.setSkullTexture(item, texture); meta = (SkullMeta) item.getItemMeta(); } @@ -254,8 +245,8 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onBlockPlace(BlockDropItemEvent e) { - if (!(e.getBlockState() instanceof Skull skull)) return; + public void onBlockPlace(BlockDropItemEvent event) { + if (!(event.getBlockState() instanceof Skull skull)) return; PDCUtil.getString(skull, this.skullKey).ifPresent(type -> { EntityType entityType = StringUtil.getEnum(type, EntityType.class).orElse(null); @@ -264,12 +255,12 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea String texture = this.headTextures.get(entityType); if (texture == null) return; - e.getItems().forEach(item -> { + event.getItems().forEach(item -> { ItemStack drop = item.getItemStack(); if (drop.getType() == Material.PLAYER_HEAD) { ItemUtil.setSkullTexture(drop, texture); - ItemUtil.mapMeta(drop, meta -> { - String name = this.headName.replace(Placeholders.GENERIC_TYPE, LangManager.getEntityType(entityType)); + ItemUtil.editMeta(drop, meta -> { + String name = this.headName.replace(GENERIC_TYPE, LangAssets.get(entityType)); meta.setDisplayName(name); PDCUtil.set(meta, this.skullKey, type); }); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantExhaust.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantExhaust.java deleted file mode 100644 index d00d06d..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantExhaust.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Material; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantExhaust extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "exhaust"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantExhaust(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "20.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.HUNGER, false, - "3.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 1.5", - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.itemCrack(Material.ROTTEN_FLESH).play(victim.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantIceAspect.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantIceAspect.java deleted file mode 100644 index ff3352b..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantIceAspect.java +++ /dev/null @@ -1,85 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Material; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantIceAspect extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "ice_aspect"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantIceAspect(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Freezes and applies " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, "100"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.SLOW, false, - "3.0 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - victim.setFreezeTicks(victim.getMaxFreezeTicks()); - - if (this.hasVisualEffects()) { - UniParticle.blockCrack(Material.ICE).play(victim.getEyeLocation(), 0.25, 0.15, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantParalyze.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantParalyze.java deleted file mode 100644 index e0554e6..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantParalyze.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantParalyze extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "paralyze"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantParalyze(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.SLOW_DIGGING, false, - "2.5 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.5", - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.of(Particle.CRIT_MAGIC).play(victim.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantRage.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantRage.java deleted file mode 100644 index 8ecb555..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantRage.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantRage extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "rage"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantRage(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to get " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "7.0 + " + Placeholders.ENCHANTMENT_LEVEL); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.INCREASE_DAMAGE, false, - "3.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.5", - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(damager, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.of(Particle.LAVA).play(damager.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantScavenger.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantScavenger.java deleted file mode 100644 index df514bf..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantScavenger.java +++ /dev/null @@ -1,131 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Material; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityResurrectEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.Pair; -import su.nexmedia.engine.utils.StringUtil; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; - -import java.util.HashMap; -import java.util.Map; - -public class EnchantScavenger extends ExcellentEnchant implements Chanced, DeathEnchant { - - public static final String ID = "scavenger"; - - private Map>> loot; - - private ChanceImplementation chanceImplementation; - - public EnchantScavenger(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to obtain additional loot from mobs."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "15.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 10"); - - this.loot = new HashMap<>(); - - if (!this.cfg.contains("Settings.Treasures")) { - cfg.addMissing("Settings.Treasures.VILLAGER.EMERALD.Amount", "1:1"); - cfg.addMissing("Settings.Treasures.VILLAGER.EMERALD.Chance", "50"); - - cfg.addMissing("Settings.Treasures.SKELETON.BONE_MEAL.Amount", "1:2"); - cfg.addMissing("Settings.Treasures.SKELETON.BONE_MEAL.Chance", "50"); - - cfg.saveChanges(); - } - - for (String eId : cfg.getSection("Settings.Treasures")) { - EntityType eType = StringUtil.getEnum(eId, EntityType.class).orElse(null); - if (eType == null || !eType.isAlive()) { - plugin.error("[Scavenger] Invalid entity type '" + eId + "' !"); - continue; - } - - Map> items = new HashMap<>(); - for (String sFromArray : cfg.getSection("Settings.Treasures." + eId)) { - Material material = Material.getMaterial(sFromArray.toUpperCase()); - if (material == null) { - plugin.error("[Scavenger] Invalid item material '" + sFromArray + "' !"); - continue; - } - - String path = "Settings.Treasures." + eId + "." + sFromArray + "."; - String[] amountSplit = cfg.getString(path + "Amount", "1:1").split(":"); - int amountMin = StringUtil.getInteger(amountSplit[0], 1); - int amountMax = StringUtil.getInteger(amountSplit[1], 1); - int[] amount = new int[]{amountMin, amountMax}; - - double chance = cfg.getDouble(path + "Chance"); - if (chance <= 0) continue; - - Pair item = Pair.of(amount, chance); - items.put(material, item); - } - this.loot.put(eType, items); - } - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @Override - @NotNull - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @Override - public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, ItemStack weapon, int level) { - Map> items = this.loot.get(entity.getType()); - if (items == null) return false; - - if (!this.checkTriggerChance(level)) return false; - - items.forEach((material, data) -> { - double chance = data.getSecond(); - if (Rnd.get(true) > chance) return; - - int amount = Rnd.get(data.getFirst()[0], data.getFirst()[1]); - if (amount <= 0) return; - - ItemStack item = new ItemStack(material); - event.getDrops().add(item); - }); - - return true; - } - - @Override - public boolean onDeath(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, ItemStack item, int level) { - return false; - } - - @Override - public boolean onResurrect(@NotNull EntityResurrectEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantSurprise.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantSurprise.java deleted file mode 100644 index 1407c63..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantSurprise.java +++ /dev/null @@ -1,91 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Color; -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.random.Rnd; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantSurprise extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "surprise"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantSurprise(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply random potion effect to enemy on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.75); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "2.25 * " + Placeholders.ENCHANTMENT_LEVEL); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.BLINDNESS, false, - "3.0 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - - PotionEffect effect = new PotionEffect(Rnd.get(PotionEffectType.values()), this.getEffectDuration(level), Math.max(0, this.getEffectAmplifier(level) - 1), false, false); - if (!victim.addPotionEffect(effect)) return false; - - if (this.hasVisualEffects()) { - Color color = Color.fromRGB(Rnd.nextInt(256), Rnd.nextInt(256), Rnd.nextInt(256)); - Particle.DustOptions dustOptions = new Particle.DustOptions(color, 2f); - UniParticle.of(Particle.REDSTONE, dustOptions).play(victim.getEyeLocation(), 0.25, 0.1, 25); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantTemper.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantTemper.java deleted file mode 100644 index 244c4cb..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantTemper.java +++ /dev/null @@ -1,99 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.attribute.Attribute; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.EntityUtil; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; - -public class EnchantTemper extends ExcellentEnchant implements CombatEnchant { - - public static final String ID = "temper"; - public static final String PLACEHOLDER_DAMAGE_AMOUNT = "%enchantment_damage_amount%"; - public static final String PLACEHOLDER_DAMAGE_CAPACITY = "%enchantment_damage_capacity%"; - public static final String PLACEHOLDER_HEALTH_POINT = "%enchantment_health_point%"; - - private EnchantScaler damageAmount; - private EnchantScaler damageCapacity; - private EnchantScaler healthPoint; - - public EnchantTemper(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Inflicts " + PLACEHOLDER_DAMAGE_AMOUNT + "% (max. " + PLACEHOLDER_DAMAGE_CAPACITY + "%) more damage for each " + PLACEHOLDER_HEALTH_POINT + " hearts missing."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.3); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.damageAmount = EnchantScaler.read(this, "Settings.Damage.Amount", - "0.01 * " + Placeholders.ENCHANTMENT_LEVEL, - "On how much (in percent) the damage will be increased per each Health Point?"); - this.damageCapacity = EnchantScaler.read(this, "Settings.Damage.Capacity", "2.0", - "Maximal possible value for the Damage.Amount."); - this.healthPoint = EnchantScaler.read(this, "Settings.Health.Point", "0.5", - "For how much every missing hearts damage will be increased?"); - - this.addPlaceholder(PLACEHOLDER_DAMAGE_AMOUNT, level -> NumberUtil.format(this.getDamageAmount(level) * 100D)); - this.addPlaceholder(PLACEHOLDER_DAMAGE_CAPACITY, level -> NumberUtil.format(this.getDamageCapacity(level) * 100D)); - this.addPlaceholder(PLACEHOLDER_HEALTH_POINT, level -> NumberUtil.format(this.getHealthPoint(level))); - } - - public double getDamageAmount(int level) { - return this.damageAmount.getValue(level); - } - - public double getDamageCapacity(int level) { - return this.damageCapacity.getValue(level); - } - - public double getHealthPoint(int level) { - return this.healthPoint.getValue(level); - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.NORMAL; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - double healthPoint = this.getHealthPoint(level); - double healthHas = damager.getHealth(); - double healthMax = EntityUtil.getAttribute(damager, Attribute.GENERIC_MAX_HEALTH); - double healthDiff = healthMax - healthHas; - if (healthHas >= healthMax || healthDiff < healthPoint) return false; - - int pointAmount = (int) (healthDiff / healthPoint); - if (pointAmount == 0) return false; - - double damageAmount = this.getDamageAmount(level); - double damageCap = this.getDamageCapacity(level); - double damageFinal = Math.min(damageCap, 1D + damageAmount * pointAmount); - - event.setDamage(event.getDamage() * damageFinal); - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantThrifty.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantThrifty.java deleted file mode 100644 index 4775865..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantThrifty.java +++ /dev/null @@ -1,123 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.NamespacedKey; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityResurrectEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.EngineUtils; -import su.nexmedia.engine.utils.PDCUtil; -import su.nexmedia.engine.utils.StringUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.hook.HookId; -import su.nightexpress.excellentenchants.hook.impl.MythicMobsHook; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -public class EnchantThrifty extends ExcellentEnchant implements Chanced, DeathEnchant, EventListener { - - public static final String ID = "thrifty"; - - private final NamespacedKey keyEntityIgnored; - - private Set ignoredEntityTypes; - private Set ignoredSpawnReasons; - private boolean ignoreMythicMobs; - - private ChanceImplementation chanceImplementation; - - public EnchantThrifty(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to obtain mob spawn egg on kill."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.75); - - this.keyEntityIgnored = new NamespacedKey(plugin, ID + "_ignored"); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "5.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 3"); - - this.ignoredEntityTypes = JOption.create("Settings.Ignored_Entity_Types", - Set.of(EntityType.WITHER.name(), EntityType.ENDER_DRAGON.name()), - "List of entity types, that will not drop spawn eggs.", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html" - ).read(cfg).stream().map(e -> StringUtil.getEnum(e, EntityType.class).orElse(null)) - .filter(Objects::nonNull).collect(Collectors.toSet()); - - this.ignoredSpawnReasons = JOption.create("Settings.Ignored_Spawn_Reasons", - Set.of(CreatureSpawnEvent.SpawnReason.SPAWNER_EGG.name(), - CreatureSpawnEvent.SpawnReason.SPAWNER.name(), - CreatureSpawnEvent.SpawnReason.DISPENSE_EGG.name()), - "Entities will not drop spawn eggs if they were spawned by one of the reasons below.", - "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/entity/CreatureSpawnEvent.SpawnReason.html" - ).read(cfg).stream().map(e -> StringUtil.getEnum(e, CreatureSpawnEvent.SpawnReason.class).orElse(null)) - .filter(Objects::nonNull).collect(Collectors.toSet()); - - this.ignoreMythicMobs = JOption.create("Settings.Ignore_MythicMobs", true, - "Sets whether or not MythicMobs should be immune to enchantment effect." - ).read(cfg); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @Override - @NotNull - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @Override - public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, ItemStack weapon, int level) { - if (this.ignoredEntityTypes.contains(entity.getType())) return false; - if (PDCUtil.getBoolean(entity, this.keyEntityIgnored).orElse(false)) return false; - if (this.ignoreMythicMobs && EngineUtils.hasPlugin(HookId.MYTHIC_MOBS) && MythicMobsHook.isMythicMob(entity)) return false; - if (!this.checkTriggerChance(level)) return false; - - ItemStack eggItem = plugin.getEnchantNMS().getSpawnEgg(entity); - if (eggItem == null) return false; - - event.getDrops().add(eggItem); - return true; - } - - @Override - public boolean onDeath(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, ItemStack item, int level) { - return false; - } - - @Override - public boolean onResurrect(@NotNull EntityResurrectEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level) { - return false; - } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onCreatureSpawn(CreatureSpawnEvent event) { - if (!this.ignoredSpawnReasons.contains(event.getSpawnReason())) return; - - PDCUtil.set(event.getEntity(), this.keyEntityIgnored, true); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantThunder.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantThunder.java deleted file mode 100644 index 5dbfb3f..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantThunder.java +++ /dev/null @@ -1,95 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.metadata.FixedMetadataValue; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; - -public class EnchantThunder extends ExcellentEnchant implements Chanced, CombatEnchant { - - public static final String ID = "thunder"; - - private static final String META_NO_ITEM_DAMAGE = "noItemDamage"; - - private boolean inThunderstormOnly; - private ChanceImplementation chanceImplementation; - - public EnchantThunder(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to summon lightning to enemy on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 * " + Placeholders.ENCHANTMENT_LEVEL); - this.inThunderstormOnly = JOption.create("Settings.During_Thunderstorm_Only", false, - "When 'true' the enchantment will be triggered only if there is an active thunderstorm in the world.").read(cfg); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - public boolean isInThunderstormOnly() { - return inThunderstormOnly; - } - - @Override - @NotNull - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (this.isInThunderstormOnly() && !victim.getWorld().isThundering()) return false; - if (victim.getLocation().getBlock().getLightFromSky() != 15) return false; - if (!this.checkTriggerChance(level)) return false; - - plugin.getServer().getScheduler().runTask(plugin, () -> { - if (victim.isDead()) return; - victim.setNoDamageTicks(0); - victim.getWorld().strikeLightning(victim.getLocation()).setMetadata(META_NO_ITEM_DAMAGE, new FixedMetadataValue(plugin, true)); - }); - - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onItemDamage(EntityDamageByEntityEvent e) { - if (!e.getDamager().hasMetadata(META_NO_ITEM_DAMAGE)) return; - if (!(e.getEntity() instanceof Item item)) return; - - e.setCancelled(true); - item.setFireTicks(0); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVenom.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVenom.java deleted file mode 100644 index 371145a..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVenom.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantVenom extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "venom"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantVenom(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.3); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "30.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 10.0"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.POISON, false, - "2.0 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.of(Particle.SLIME).play(victim.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantWither.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantWither.java deleted file mode 100644 index 5a82a35..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantWither.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.impl.weapon; - -import org.bukkit.Particle; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.LivingEntity; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; -import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned; -import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; -import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation; - -public class EnchantWither extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant { - - public static final String ID = "wither"; - - private ChanceImplementation chanceImplementation; - private PotionImplementation potionImplementation; - - public EnchantWither(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to apply " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " (" + Placeholders.ENCHANTMENT_POTION_DURATION + "s.) on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); - } - - @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5"); - this.potionImplementation = PotionImplementation.create(this, PotionEffectType.WITHER, false, - "3.0 + " + Placeholders.ENCHANTMENT_LEVEL, - Placeholders.ENCHANTMENT_LEVEL); - } - - @NotNull - @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; - } - - @NotNull - @Override - public PotionImplementation getPotionImplementation() { - return potionImplementation; - } - - @NotNull - @Override - public EnchantmentTarget getCategory() { - return EnchantmentTarget.WEAPON; - } - - @NotNull - @Override - public EventPriority getAttackPriority() { - return EventPriority.HIGHEST; - } - - @Override - public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - if (!this.checkTriggerChance(level)) return false; - if (!this.addEffect(victim, level)) return false; - - if (this.hasVisualEffects()) { - UniParticle.of(Particle.ASH).play(victim.getEyeLocation(), 0.25, 0.1, 30); - } - return true; - } - - @Override - public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { - return false; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ExhaustEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ExhaustEnchant.java new file mode 100644 index 0000000..85a1bce --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ExhaustEnchant.java @@ -0,0 +1,93 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Material; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ExhaustEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "exhaust"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public ExhaustEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(5, 5, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.HUNGER, false, + Modifier.add(8, 2, 1, 600), + Modifier.add(0, 1, 1, 10) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.itemCrack(Material.ROTTEN_FLESH).play(victim.getEyeLocation(), 0.25, 0.1, 30); + } + + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/IceAspectEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/IceAspectEnchant.java new file mode 100644 index 0000000..706e67d --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/IceAspectEnchant.java @@ -0,0 +1,99 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; +import su.nightexpress.nightcore.util.wrapper.UniSound; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class IceAspectEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "ice_aspect"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public IceAspectEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Freezes and applies " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.SLOW, false, + Modifier.add(4, 2, 1, 600), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + victim.setFreezeTicks(victim.getMaxFreezeTicks()); + + if (this.hasVisualEffects()) { + UniParticle.blockCrack(Material.ICE).play(victim.getEyeLocation(), 0.5, 0.1, 35); + UniParticle.of(Particle.CLOUD).play(victim.getEyeLocation(), 0.25, 0.1, 25); + UniSound.of(Sound.BLOCK_GLASS_BREAK).play(victim.getLocation()); + } + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantInfernus.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/InfernusEnchant.java similarity index 53% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantInfernus.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/InfernusEnchant.java index 8697e8a..bed294c 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantInfernus.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/InfernusEnchant.java @@ -10,37 +10,40 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.manager.EventListener; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.GenericEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.manager.SimpeListener; +import su.nightexpress.nightcore.util.NumberUtil; -public class EnchantInfernus extends ExcellentEnchant implements GenericEnchant, EventListener { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class InfernusEnchant extends AbstractEnchantmentData implements GenericEnchant, SimpeListener { public static final String ID = "infernus"; - public static final String PLACEHOLDER_FIRE_DURATION = "%enchantment_fire_duration%"; - private EnchantScaler fireTicks; + private Modifier fireTicks; - public EnchantInfernus(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Launched trident will ignite the enemy for " + PLACEHOLDER_FIRE_DURATION + "s. on hit."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.1); + public InfernusEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Launched trident will ignite the enemy for " + GENERIC_TIME + "s. on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.fireTicks = EnchantScaler.read(this, "Settings.Fire_Ticks", - "60 + " + Placeholders.ENCHANTMENT_LEVEL + " * 20", + protected void loadAdditional(@NotNull FileConfig config) { + this.fireTicks = Modifier.read(config, "Settings.Fire_Ticks", + Modifier.add(60, 20, 1, 60 * 20), "Sets for how long (in ticks) entity will be ignited on hit. 20 ticks = 1 second."); - this.addPlaceholder(PLACEHOLDER_FIRE_DURATION, level -> NumberUtil.format((double) this.getFireTicks(level) / 20D)); + this.addPlaceholder(GENERIC_TIME, level -> NumberUtil.format((double) this.getFireTicks(level) / 20D)); } public int getFireTicks(int level) { @@ -54,31 +57,31 @@ public class EnchantInfernus extends ExcellentEnchant implements GenericEnchant, } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onInfernusTridentLaunch(ProjectileLaunchEvent e) { - Entity entity = e.getEntity(); + public void onInfernusTridentLaunch(ProjectileLaunchEvent event) { + Entity entity = event.getEntity(); if (!(entity instanceof Trident trident)) return; if (!(trident.getShooter() instanceof LivingEntity shooter)) return; if (!this.isAvailableToUse(shooter)) return; ItemStack item = trident.getItem(); - int level = EnchantUtils.getLevel(item, this.getBackend()); + int level = EnchantUtils.getLevel(item, this.getEnchantment()); if (level <= 0) return; trident.setFireTicks(Integer.MAX_VALUE); } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onInfernusDamageApply(EntityDamageByEntityEvent e) { - Entity entity = e.getDamager(); + public void onInfernusDamageApply(EntityDamageByEntityEvent event) { + Entity entity = event.getDamager(); if (!(entity instanceof Trident trident)) return; ItemStack item = trident.getItem(); - int level = EnchantUtils.getLevel(item, this.getBackend()); + int level = EnchantUtils.getLevel(item, this.getEnchantment()); if (level <= 0 || trident.getFireTicks() <= 0) return; int ticks = this.getFireTicks(level); - e.getEntity().setFireTicks(ticks); + event.getEntity().setFireTicks(ticks); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantNimble.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/NimbleEnchant.java similarity index 53% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantNimble.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/NimbleEnchant.java index d3c38c5..9116154 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantNimble.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/NimbleEnchant.java @@ -8,36 +8,40 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.PlayerUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.Players; -public class EnchantNimble extends ExcellentEnchant implements Chanced, DeathEnchant { +import java.io.File; + +public class NimbleEnchant extends AbstractEnchantmentData implements ChanceData, DeathEnchant { public static final String ID = "nimble"; - private ChanceImplementation chanceImplementation; + private ChanceSettingsImpl chanceSettings; - public EnchantNimble(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Moves all mob's loot directly to your inventory."); - this.getDefaults().setLevelMax(1); - this.getDefaults().setTier(0.4); + public NimbleEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Moves all mob's loot directly to your inventory."); + this.setMaxLevel(1); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } @NotNull @@ -56,7 +60,7 @@ public class EnchantNimble extends ExcellentEnchant implements Chanced, DeathEnc public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, ItemStack weapon, int level) { if (!this.checkTriggerChance(level)) return false; - event.getDrops().forEach(item -> PlayerUtil.addItem(killer, item)); + event.getDrops().forEach(item -> Players.addItem(killer, item)); event.getDrops().clear(); return true; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ParalyzeEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ParalyzeEnchant.java new file mode 100644 index 0000000..299568a --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ParalyzeEnchant.java @@ -0,0 +1,93 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ParalyzeEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "paralyze"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public ParalyzeEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(2, 3, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.SLOW_DIGGING, false, + Modifier.add(3.5, 0.5, 1, 60), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.of(Particle.CRIT_MAGIC).play(victim.getEyeLocation(), 0.25, 0.1, 30); + } + + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/RageEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/RageEnchant.java new file mode 100644 index 0000000..b3b1280 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/RageEnchant.java @@ -0,0 +1,92 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class RageEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "rage"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public RageEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to get " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(4, 2, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.INCREASE_DAMAGE, false, + Modifier.add(3, 1, 1, 300), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(damager, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.of(Particle.LAVA).play(damager.getEyeLocation(), 0.25, 0.1, 30); + } + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantRocket.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/RocketEnchant.java similarity index 58% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantRocket.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/RocketEnchant.java index 6f41148..84b1053 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantRocket.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/RocketEnchant.java @@ -10,44 +10,49 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.random.Rnd; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.random.Rnd; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class EnchantRocket extends ExcellentEnchant implements Chanced, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class RocketEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "rocket"; - private EnchantScaler fireworkPower; - private ChanceImplementation chanceImplementation; + private Modifier fireworkPower; + private ChanceSettingsImpl chanceSettings; - public EnchantRocket(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch your enemy into the space."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.5); + public RocketEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to launch your enemy into the space."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "4.0 + " + Placeholders.ENCHANTMENT_LEVEL); - this.fireworkPower = EnchantScaler.read(this, "Settings.Firework_Power", - Placeholders.ENCHANTMENT_LEVEL + " * 0.25", + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.multiply(2, 1, 1, 100)); + + this.fireworkPower = Modifier.read(config, "Settings.Firework_Power", + Modifier.multiply(1, 0.25, 1, 3), "Firework power. The more power = the higher fly distance."); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public final double getFireworkPower(int level) { @@ -74,7 +79,7 @@ public class EnchantRocket extends ExcellentEnchant implements Chanced, CombatEn victim.leaveVehicle(); } - Firework firework = this.createRocket(victim.getLocation(), level); + Firework firework = this.createRocket(victim.getWorld(), victim.getLocation(), level); firework.addPassenger(victim); UniSound.of(Sound.ENTITY_FIREWORK_ROCKET_LAUNCH).play(victim.getLocation()); @@ -82,12 +87,7 @@ public class EnchantRocket extends ExcellentEnchant implements Chanced, CombatEn } @NotNull - private Firework createRocket(@NotNull Location location, int level) { - World world = location.getWorld(); - if (world == null) { - throw new IllegalStateException("World is null!"); - } - + private Firework createRocket(@NotNull World world, @NotNull Location location, int level) { Firework firework = (Firework) world.spawnEntity(location, EntityType.FIREWORK); FireworkMeta meta = firework.getFireworkMeta(); FireworkEffect.Type type = Rnd.get(FireworkEffect.Type.values()); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ScavengerEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ScavengerEnchant.java new file mode 100644 index 0000000..5d50780 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ScavengerEnchant.java @@ -0,0 +1,152 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityResurrectEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.loot.LootContext; +import org.bukkit.loot.LootTable; +import org.bukkit.loot.LootTables; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.random.Rnd; + +import java.io.File; +import java.util.*; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ScavengerEnchant extends AbstractEnchantmentData implements ChanceData, DeathEnchant { + + public static final String ID = "scavenger"; + + private final Set ignoredSpawnReasons; + private final Set ignoredEntities; + private final Set lootTables; + + private ChanceSettingsImpl chanceSettings; + + public ScavengerEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to get additional loot from mobs."); + this.setMaxLevel(4); + this.setRarity(Rarity.RARE); + + this.ignoredSpawnReasons = new HashSet<>(); + this.ignoredEntities = new HashSet<>(); + this.lootTables = new HashSet<>(); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(1, 0.5, 1)); + + this.ignoredSpawnReasons.addAll(ConfigValue.forSet("Settings.Ignored_SpawnReasons", + id -> StringUtil.getEnum(id, CreatureSpawnEvent.SpawnReason.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of( + CreatureSpawnEvent.SpawnReason.SPAWNER, + CreatureSpawnEvent.SpawnReason.SPAWNER_EGG, + CreatureSpawnEvent.SpawnReason.DISPENSE_EGG + ), + "Mobs spawned by specified souces will be 'immune' to this enchantment's effect.", + "https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/entity/CreatureSpawnEvent.SpawnReason.html" + ).read(config)); + + this.ignoredEntities.addAll(ConfigValue.forSet("Settings.Ignored_Entities", + id -> StringUtil.getEnum(id, EntityType.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of(EntityType.COD, EntityType.PUFFERFISH, EntityType.SQUID, EntityType.ARMOR_STAND, EntityType.SALMON), + "A list of entity types excluded from this enchantment's effect.", + "https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html" + ).read(config)); + + boolean isWhitelist = ConfigValue.create("Settings.LootTables.Whitelist", + false, + "When 'true', uses only loot tables listed below.", + "When 'false', uses ALL loot tables except ones listed below.", + "[Default is false]" + ).read(config); + + Set tables = ConfigValue.forSet("Settings.LootTables.List", + id -> StringUtil.getEnum(id, LootTables.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of( + LootTables.ENDER_DRAGON, + LootTables.END_CITY_TREASURE, + LootTables.PILLAGER_OUTPOST, + LootTables.NETHER_BRIDGE, + LootTables.BASTION_BRIDGE + ), + "List of loot tables that are added or excluded (depends on Whitelist setting) for this enchantment.", + "Available loot table names: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/loot/LootTables.html" + ).read(config); + + if (isWhitelist) { + this.lootTables.addAll(tables); + } + else { + this.lootTables.addAll(Arrays.asList(LootTables.values())); + this.lootTables.removeAll(tables); + } + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @Override + @NotNull + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @Override + public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, @NotNull ItemStack weapon, int level) { + if (this.lootTables.isEmpty()) return false; + if (this.ignoredEntities.contains(entity.getType())) return false; + + CreatureSpawnEvent.SpawnReason spawnReason = EnchantUtils.getSpawnReason(entity); + if (spawnReason != null && this.ignoredSpawnReasons.contains(spawnReason)) return false; + + if (!this.checkTriggerChance(level)) return false; + + LootTable lootTable = Rnd.get(this.lootTables).getLootTable(); + LootContext.Builder builder = new LootContext.Builder(entity.getLocation()); + builder.killer(killer); + builder.lootedEntity(entity); + LootContext context = builder.build(); + + Collection items = lootTable.populateLoot(Rnd.RANDOM, context); + + event.getDrops().addAll(items); + return true; + } + + @Override + public boolean onDeath(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, ItemStack item, int level) { + return false; + } + + @Override + public boolean onResurrect(@NotNull EntityResurrectEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SurpriseEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SurpriseEnchant.java new file mode 100644 index 0000000..51cc935 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SurpriseEnchant.java @@ -0,0 +1,101 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Color; +import org.bukkit.Particle; +import org.bukkit.Registry; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.BukkitThing; +import su.nightexpress.nightcore.util.random.Rnd; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SurpriseEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "surprise"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public SurpriseEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply random potion effect to enemy on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3, 2, 1)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.BLINDNESS, false, + Modifier.add(4, 1, 1, 900), + Modifier.add(0, 1, 1, 10) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + + PotionEffect effect = new PotionEffect(Rnd.get(BukkitThing.allFromRegistry(Registry.EFFECT)), this.getEffectDuration(level), Math.max(0, this.getEffectAmplifier(level) - 1), false, false); + if (!victim.addPotionEffect(effect)) return false; + + if (this.hasVisualEffects()) { + Color color = Color.fromRGB(Rnd.nextInt(256), Rnd.nextInt(256), Rnd.nextInt(256)); + Particle.DustOptions dustOptions = new Particle.DustOptions(color, 2f); + UniParticle.of(Particle.REDSTONE, dustOptions).play(victim.getEyeLocation(), 0.25, 0.1, 25); + } + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SwiperEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SwiperEnchant.java index 1d6f989..0b8c354 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SwiperEnchant.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/SwiperEnchant.java @@ -6,40 +6,43 @@ import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class SwiperEnchant extends ExcellentEnchant implements CombatEnchant, Chanced { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class SwiperEnchant extends AbstractEnchantmentData implements CombatEnchant, ChanceData { public static final String ID = "swiper"; public static final String PLACEHOLER_XP_AMOUNT = "%xp_amount%"; - private ChanceImplementation chanceImplementation; - private EnchantScaler xpAmount; + private ChanceSettingsImpl chanceSettings; + private Modifier xpAmount; - public SwiperEnchant(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to steal " + PLACEHOLER_XP_AMOUNT + " XP from players."); - this.getDefaults().setLevelMax(3); - this.getDefaults().setTier(0.7); + public SwiperEnchant(@NotNull ExcellentEnchantsPlugin plugin, File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to steal " + PLACEHOLER_XP_AMOUNT + " XP from players."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(5, 2.5, 1)); - this.chanceImplementation = ChanceImplementation.create(this, - "5.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 2.5"); - - this.xpAmount = EnchantScaler.read(this, "Settings.XP_Amount", - Placeholders.ENCHANTMENT_LEVEL, + this.xpAmount = Modifier.read(config, "Settings.XP_Amount", + Modifier.add(0, 1, 1), "Amount of XP to be stolen on hit."); this.addPlaceholder(PLACEHOLER_XP_AMOUNT, level -> NumberUtil.format(this.getXPAmount(level))); @@ -53,8 +56,8 @@ public class SwiperEnchant extends ExcellentEnchant implements CombatEnchant, Ch @NotNull @Override - public Chanced getChanceImplementation() { - return this.chanceImplementation; + public ChanceSettings getChanceSettings() { + return this.chanceSettings; } public int getXPAmount(int level) { @@ -68,7 +71,7 @@ public class SwiperEnchant extends ExcellentEnchant implements CombatEnchant, Ch } private void addXP(@NotNull Player player, int amount) { - int levelHas = player.getLevel(); + //int levelHas = player.getLevel(); int xpHas = player.getTotalExperience(); xpHas = Math.max(0, xpHas + amount); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/TemperEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/TemperEnchant.java new file mode 100644 index 0000000..e8f250c --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/TemperEnchant.java @@ -0,0 +1,90 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.attribute.Attribute; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.EntityUtil; +import su.nightexpress.nightcore.util.NumberUtil; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class TemperEnchant extends AbstractEnchantmentData implements CombatEnchant { + + public static final String ID = "temper"; + + private Modifier damageAmount; + private Modifier damageStep; + + public TemperEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription("Inflicts " + GENERIC_AMOUNT + "% more damage for each " + GENERIC_RADIUS + "❤ missing."); + this.setMaxLevel(5); + this.setRarity(Rarity.UNCOMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.damageAmount = Modifier.read(config, "Settings.Damage.Amount", + Modifier.add(0, 5, 1, 100), + "Extra damage (in %)"); + + this.damageStep = Modifier.read(config, "Settings.Damage.Step", + Modifier.add(0.5, 0, 0), + "Damage will be increased for every X entity's health points missing. Where X is this value.", + "By default increases damage by 5% for every 0.5 HP missing." + ); + + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getDamageAmount(level))); + this.addPlaceholder(GENERIC_RADIUS, level -> NumberUtil.format(this.getDamageStep(level))); + } + + public double getDamageAmount(int level) { + return this.damageAmount.getValue(level); + } + + public double getDamageStep(int level) { + return this.damageStep.getValue(level); + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + double health = damager.getHealth(); + double maxHealth = EntityUtil.getAttribute(damager, Attribute.GENERIC_MAX_HEALTH); + if (health >= maxHealth) return false; + + double missingHealth = maxHealth - health; + double step = this.getDamageStep(level); + if (step == 0 || missingHealth < step) return false; + + double steps = Math.floor(missingHealth / step); + if (steps == 0) return false; + + double percent = this.getDamageAmount(level) / 100D; + double damagePercent = percent * steps; + + event.setDamage(event.getDamage() * damagePercent); + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ThriftyEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ThriftyEnchant.java new file mode 100644 index 0000000..f059d0b --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ThriftyEnchant.java @@ -0,0 +1,130 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Material; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityResurrectEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.excellentenchants.hook.HookId; +import su.nightexpress.excellentenchants.hook.impl.MythicMobsHook; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.BukkitThing; +import su.nightexpress.nightcore.util.Plugins; +import su.nightexpress.nightcore.util.StringUtil; +import su.nightexpress.nightcore.util.Version; + +import java.io.File; +import java.util.Set; + +import static su.nightexpress.excellentenchants.Placeholders.*; +import static org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; + +public class ThriftyEnchant extends AbstractEnchantmentData implements ChanceData, DeathEnchant { + + public static final String ID = "thrifty"; + + private Set ignoredEntityTypes; + private Set ignoredSpawnReasons; + private boolean ignoreMythicMobs; + + private ChanceSettingsImpl chanceSettings; + + public ThriftyEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance for mobs to drop spawn egg."); + this.setMaxLevel(3); + this.setRarity(Rarity.RARE); + } + + @Override + public boolean checkServerRequirements() { + if (!Version.isAtLeast(Version.V1_20_R2)) { + this.warn("Enchantment available only for version " + Version.V1_20_R2.getLocalized() + " or above!"); + return false; + } + return true; + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(1, 1, 1, 100)); + + this.ignoredEntityTypes = ConfigValue.forSet("Settings.Ignored_Mobs", + BukkitThing::getEntityType, + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of(EntityType.WITHER, EntityType.ENDER_DRAGON), + "List of mobs exempted from this enchantment." + ).read(config); + + this.ignoredSpawnReasons = ConfigValue.forSet("Settings.Ignored_Spawn_Reasons", + id -> StringUtil.getEnum(id, SpawnReason.class).orElse(null), + (cfg, path, set) -> cfg.set(path, set.stream().map(Enum::name).toList()), + Set.of( + SpawnReason.SPAWNER_EGG, + SpawnReason.SPAWNER, + SpawnReason.DISPENSE_EGG + ), + "List of mobs exempted from this enchantment when spawned by specified reasons.", + "https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/entity/CreatureSpawnEvent.SpawnReason.html" + ).read(config); + + this.ignoreMythicMobs = ConfigValue.create("Settings.Ignored_MythicMobs", + true, + "Sets whether or not MythicMobs should be exempted from this enchantment." + ).read(config); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @Override + @NotNull + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @Override + public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, ItemStack weapon, int level) { + if (this.ignoredEntityTypes.contains(entity.getType())) return false; + if (this.ignoreMythicMobs && Plugins.isLoaded(HookId.MYTHIC_MOBS) && MythicMobsHook.isMythicMob(entity)) return false; + + SpawnReason spawnReason = EnchantUtils.getSpawnReason(entity); + if (spawnReason != null && this.ignoredSpawnReasons.contains(spawnReason)) return false; + + if (!this.checkTriggerChance(level)) return false; + + Material material = plugin.getServer().getItemFactory().getSpawnEgg(entity.getType()); + if (material == null) return false; + + ItemStack eggItem = new ItemStack(material); + event.getDrops().add(eggItem); + return true; + } + + @Override + public boolean onDeath(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, ItemStack item, int level) { + return false; + } + + @Override + public boolean onResurrect(@NotNull EntityResurrectEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ThunderEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ThunderEnchant.java new file mode 100644 index 0000000..d6b1f14 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/ThunderEnchant.java @@ -0,0 +1,107 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.LocationUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class ThunderEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { + + public static final String ID = "thunder"; + + private boolean thunderstormOnly; + private ChanceSettingsImpl chanceSettings; + private Modifier damageModifier; + + public ThunderEnchant(@NotNull ExcellentEnchantsPlugin plugin, File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to strike lightning with " + GENERIC_DAMAGE + "❤ extra damage."); + this.setMaxLevel(5); + this.setRarity(Rarity.UNCOMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(5, 2, 1, 100)); + + this.thunderstormOnly = ConfigValue.create("Settings.During_Thunderstorm_Only", + false, + "Sets whether or not enchantment will have effect only during thunderstorm in the world." + ).read(config); + + this.damageModifier = Modifier.read(config, "Settings.Damage_Modifier", + Modifier.add(1.25, 0.25, 1, 10000), + "Sets additional damage caused by enchantment's effect." + ); + + this.addPlaceholder(GENERIC_DAMAGE, level -> NumberUtil.format(this.getDamage(level))); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + public boolean isDuringThunderstormOnly() { + return thunderstormOnly; + } + + public double getDamage(int level) { + return this.damageModifier.getValue(level); + } + + @Override + @NotNull + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (this.isDuringThunderstormOnly() && !victim.getWorld().isThundering()) return false; + if (victim.getLocation().getBlock().getLightFromSky() != 15) return false; + if (!this.checkTriggerChance(level)) return false; + + Location location = victim.getLocation(); + victim.getWorld().strikeLightningEffect(location); + + if (this.hasVisualEffects()) { + Block block = location.getBlock().getRelative(BlockFace.DOWN); + Location center = LocationUtil.getCenter(location); + UniParticle.blockCrack(block.getType()).play(center, 0.5, 0.1, 100); + UniParticle.of(Particle.FIREWORKS_SPARK).play(center, 0.75, 0.05, 120); + } + + event.setDamage(event.getDamage() + this.getDamage(level)); + + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVampire.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VampireEnchant.java similarity index 55% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVampire.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VampireEnchant.java index b388773..1c83e6f 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVampire.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VampireEnchant.java @@ -9,53 +9,59 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.EntityUtil; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.EntityUtil; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class EnchantVampire extends ExcellentEnchant implements Chanced, CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class VampireEnchant extends AbstractEnchantmentData implements ChanceData, CombatEnchant { public static final String ID = "vampire"; - public static final String PLACEHOLDER_HEAL_AMOUNT = "%enchantment_heal_amount%"; - private EnchantScaler healAmount; - private boolean healMultiplier; - private ChanceImplementation chanceImplementation; + private Modifier healAmount; + private boolean healMultiplier; + private ChanceSettingsImpl chanceSettings; - public EnchantVampire(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to heal for " + PLACEHOLDER_HEAL_AMOUNT + " heart(s) on hit."); - this.getDefaults().setLevelMax(4); - this.getDefaults().setTier(0.75); + public VampireEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to heal for " + GENERIC_AMOUNT + "❤ on hit."); + this.setMaxLevel(4); + this.setRarity(Rarity.RARE); } @Override - public void loadSettings() { - super.loadSettings(); - this.chanceImplementation = ChanceImplementation.create(this, - "25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5.0"); + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(5, 2.5, 1)); - this.healAmount = EnchantScaler.read(this, "Settings.Heal.Amount", - "0.25 * " + Placeholders.ENCHANTMENT_LEVEL, + this.healAmount = Modifier.read(config, "Settings.Heal.Amount", + Modifier.add(0, 0.25, 1, 100), "Amount of health to be restored for attacker."); - this.healMultiplier = JOption.create("Settings.Heal.As_Multiplier", false, - "When 'true', the option above will work as a multiplier of the inflicted damage.").read(cfg); - this.addPlaceholder(PLACEHOLDER_HEAL_AMOUNT, level -> NumberUtil.format(this.isHealMultiplier() ? getHealAmount(level) * 100D : getHealAmount(level))); + this.healMultiplier = ConfigValue.create("Settings.Heal.As_Multiplier", + false, + "When 'true', the option above will work as a multiplier of the inflicted damage." + ).read(config); + + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.isHealMultiplier() ? getHealAmount(level) * 100D : getHealAmount(level))); } @NotNull @Override - public ChanceImplementation getChanceImplementation() { - return chanceImplementation; + public ChanceSettings getChanceSettings() { + return chanceSettings; } public double getHealAmount(int level) { diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VenomEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VenomEnchant.java new file mode 100644 index 0000000..4e6409e --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VenomEnchant.java @@ -0,0 +1,92 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class VenomEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "venom"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public VenomEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(5, 5, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.POISON, false, + Modifier.add(3, 1, 1, 300), + Modifier.add(0, 1, 1, 10) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.of(Particle.SLIME).play(victim.getEyeLocation(), 0.25, 0.1, 30); + } + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVillageDefender.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VillageDefenderEnchant.java similarity index 55% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVillageDefender.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VillageDefenderEnchant.java index 97c6bdd..80e7d4c 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantVillageDefender.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/VillageDefenderEnchant.java @@ -7,42 +7,46 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.utils.NumberUtil; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.wrapper.UniParticle; -public class EnchantVillageDefender extends ExcellentEnchant implements CombatEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class VillageDefenderEnchant extends AbstractEnchantmentData implements CombatEnchant { public static final String ID = "village_defender"; - public static final String PLACEHOLDER_DAMAGE_AMOUNT = "%enchantment_damage_amount%"; - private boolean damageMultiplier; - private EnchantScaler damageAmount; + private boolean damageMultiplier; + private Modifier damageAmount; - public EnchantVillageDefender(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Inflicts " + PLACEHOLDER_DAMAGE_AMOUNT + " more damage to all pillagers."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.1); + public VillageDefenderEnchant(@NotNull ExcellentEnchantsPlugin plugin, File file) { + super(plugin, file); + this.setDescription("Inflicts " + GENERIC_AMOUNT + "❤ more damage to all pillagers."); + this.setMaxLevel(5); + this.setRarity(Rarity.COMMON); } @Override - public void loadSettings() { - super.loadSettings(); - - this.damageAmount = EnchantScaler.read(this, "Settings.Damage.Formula", - "0.5 * " + Placeholders.ENCHANTMENT_LEVEL, + protected void loadAdditional(@NotNull FileConfig config) { + this.damageAmount = Modifier.read(config, "Settings.Damage.Amount", + Modifier.add(0.5, 0.5, 1), "Amount of additional damage."); - this.damageMultiplier = JOption.create("Settings.Damage.As_Modifier", false, - "When 'true' the 'Damage.Formula' will work as a multiplier to the original damage.").read(cfg); + this.damageMultiplier = ConfigValue.create("Settings.Damage.As_Modifier", + false, + "When 'true' the 'Damage.Formula' will work as a multiplier to the original damage." + ).read(config); - this.addPlaceholder(PLACEHOLDER_DAMAGE_AMOUNT, level -> NumberUtil.format(this.getDamageAddict(level))); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getDamageAddict(level))); } public double getDamageAddict(int level) { diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantExpHunter.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/WisdomEnchant.java similarity index 52% rename from Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantExpHunter.java rename to Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/WisdomEnchant.java index 4c4d26b..777e9e1 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/EnchantExpHunter.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/WisdomEnchant.java @@ -7,39 +7,42 @@ import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.Placeholders; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant; -import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.NumberUtil; -public class EnchantExpHunter extends ExcellentEnchant implements DeathEnchant { +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class WisdomEnchant extends AbstractEnchantmentData implements DeathEnchant { public static final String ID = "exp_hunter"; - public static final String PLACEHOLDER_EXP_MODIFIER = "%enchantment_exp_modifier%"; - private EnchantScaler expModifier; + private Modifier xpModifier; - public EnchantExpHunter(@NotNull ExcellentEnchants plugin) { - super(plugin, ID); - this.getDefaults().setDescription("Increases exp drop from mobs by " + PLACEHOLDER_EXP_MODIFIER + "%."); - this.getDefaults().setLevelMax(5); - this.getDefaults().setTier(0.3); + public WisdomEnchant(@NotNull ExcellentEnchantsPlugin plugin, File file) { + super(plugin, file); + this.setDescription("Increases XP dropped from mobs by " + GENERIC_AMOUNT + "%."); + this.setMaxLevel(5); + this.setRarity(Rarity.UNCOMMON); } @Override - public void loadSettings() { - super.loadSettings(); - this.expModifier = EnchantScaler.read(this, "Settings.Exp_Modifier", - "1.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.5", + protected void loadAdditional(@NotNull FileConfig config) { + this.xpModifier = Modifier.read(config, "Settings.XP_Modifier", + Modifier.add(1, 0.5, 1, 5D), "Exp modifier value. The original exp amount will be multiplied on this value."); - this.addPlaceholder(PLACEHOLDER_EXP_MODIFIER, level -> NumberUtil.format(this.getExpModifier(level) * 100D - 100D)); + this.addPlaceholder(GENERIC_AMOUNT, level -> NumberUtil.format(this.getXPModifier(level) * 100D - 100D)); } - public final double getExpModifier(int level) { - return this.expModifier.getValue(level); + public final double getXPModifier(int level) { + return this.xpModifier.getValue(level); } @Override @@ -50,7 +53,7 @@ public class EnchantExpHunter extends ExcellentEnchant implements DeathEnchant { @Override public boolean onKill(@NotNull EntityDeathEvent event, @NotNull LivingEntity entity, @NotNull Player killer, ItemStack weapon, int level) { - double expModifier = this.getExpModifier(level); + double expModifier = this.getXPModifier(level); double expFinal = Math.ceil((double) event.getDroppedExp() * expModifier); event.setDroppedExp((int) expFinal); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/WitherEnchant.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/WitherEnchant.java new file mode 100644 index 0000000..e27ef4f --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/impl/weapon/WitherEnchant.java @@ -0,0 +1,92 @@ +package su.nightexpress.excellentenchants.enchantment.impl.weapon; + +import org.bukkit.Particle; +import org.bukkit.enchantments.EnchantmentTarget; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.Modifier; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceData; +import su.nightexpress.excellentenchants.api.enchantment.data.ChanceSettings; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionData; +import su.nightexpress.excellentenchants.api.enchantment.data.PotionSettings; +import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant; +import su.nightexpress.excellentenchants.enchantment.data.AbstractEnchantmentData; +import su.nightexpress.excellentenchants.enchantment.data.ChanceSettingsImpl; +import su.nightexpress.excellentenchants.enchantment.data.PotionSettingsImpl; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.io.File; + +import static su.nightexpress.excellentenchants.Placeholders.*; + +public class WitherEnchant extends AbstractEnchantmentData implements ChanceData, PotionData, CombatEnchant { + + public static final String ID = "wither"; + + private ChanceSettingsImpl chanceSettings; + private PotionSettingsImpl potionSettings; + + public WitherEnchant(@NotNull ExcellentEnchantsPlugin plugin, @NotNull File file) { + super(plugin, file); + this.setDescription(ENCHANTMENT_CHANCE + "% chance to apply " + ENCHANTMENT_POTION_TYPE + " " + ENCHANTMENT_POTION_LEVEL + " (" + ENCHANTMENT_POTION_DURATION + "s.) on hit."); + this.setMaxLevel(3); + this.setRarity(Rarity.UNCOMMON); + } + + @Override + protected void loadAdditional(@NotNull FileConfig config) { + this.chanceSettings = ChanceSettingsImpl.create(config, Modifier.add(3, 3, 1, 100)); + + this.potionSettings = PotionSettingsImpl.create(this, config, PotionEffectType.WITHER, false, + Modifier.add(4, 1, 1, 300), + Modifier.add(0, 1, 1, 5) + ); + } + + @NotNull + @Override + public ChanceSettings getChanceSettings() { + return chanceSettings; + } + + @NotNull + @Override + public PotionSettings getPotionSettings() { + return potionSettings; + } + + @NotNull + @Override + public EnchantmentTarget getCategory() { + return EnchantmentTarget.WEAPON; + } + + @NotNull + @Override + public EventPriority getAttackPriority() { + return EventPriority.HIGHEST; + } + + @Override + public boolean onAttack(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + if (!this.checkTriggerChance(level)) return false; + if (!this.addEffect(victim, level)) return false; + + if (this.hasVisualEffects()) { + UniParticle.of(Particle.ASH).play(victim.getEyeLocation(), 0.25, 0.1, 30); + } + return true; + } + + @Override + public boolean onProtect(@NotNull EntityDamageByEntityEvent event, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) { + return false; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantAnvilListener.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantAnvilListener.java index 772843c..d837f40 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantAnvilListener.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantAnvilListener.java @@ -1,33 +1,6 @@ -/* - * Decompiled with CFR 0.151. - * - * Could not load the following classes: - * org.bukkit.Material - * org.bukkit.NamespacedKey - * org.bukkit.Sound - * org.bukkit.entity.Player - * org.bukkit.event.EventHandler - * org.bukkit.event.EventPriority - * org.bukkit.event.inventory.InventoryClickEvent - * org.bukkit.event.inventory.PrepareAnvilEvent - * org.bukkit.inventory.AnvilInventory - * org.bukkit.inventory.Inventory - * org.bukkit.inventory.ItemStack - * org.bukkit.plugin.Plugin - * org.jetbrains.annotations.NotNull - * su.nexmedia.engine.NexPlugin - * su.nexmedia.engine.api.manager.AbstractListener - * su.nexmedia.engine.utils.PDCUtil - * su.nexmedia.engine.utils.values.UniSound - */ package su.nightexpress.excellentenchants.enchantment.listener; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -37,155 +10,169 @@ import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.NexPlugin; -import su.nexmedia.engine.api.manager.AbstractListener; -import su.nexmedia.engine.utils.PDCUtil; -import su.nexmedia.engine.utils.values.UniSound; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.ExcellentEnchantsAPI; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.config.Keys; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.manager.AbstractListener; +import su.nightexpress.nightcore.util.PDCUtil; +import su.nightexpress.nightcore.util.wrapper.UniSound; -public class EnchantAnvilListener extends AbstractListener { +import java.util.HashMap; +import java.util.Map; - private static final NamespacedKey RECHARGED = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "item.recharged"); +public class EnchantAnvilListener extends AbstractListener { - public EnchantAnvilListener(@NotNull ExcellentEnchants plugin) { + public EnchantAnvilListener(@NotNull ExcellentEnchantsPlugin plugin) { super(plugin); } - @EventHandler(priority=EventPriority.HIGH) + @EventHandler(priority = EventPriority.HIGH) public void onAnvilRename(PrepareAnvilEvent event) { AnvilInventory inventory = event.getInventory(); ItemStack first = inventory.getItem(0); ItemStack second = inventory.getItem(1); ItemStack result = event.getResult(); - if (first == null) { - first = new ItemStack(Material.AIR); - } - if (second == null) { - second = new ItemStack(Material.AIR); - } - if (result == null) { - result = new ItemStack(Material.AIR); - } - if (first.getType().isAir() || first.getAmount() > 1 || !EnchantUtils.isEnchantable(first)) { - return; - } - if (this.handleRename(event, first, second, result)) { - return; - } - if (this.handleRecharge(event, first, second, result)) { - return; - } - this.handleEnchantMerging(event, first, second, result); + + if (first == null) first = new ItemStack(Material.AIR); + if (second == null) second = new ItemStack(Material.AIR); + if (result == null) result = new ItemStack(Material.AIR); + + //if (first.getType().isAir() || first.getAmount() > 1 || !EnchantUtils.isEnchantable(first)) return; + + //if (this.handleRename(event, first, second, result)) return; + + if (this.handleRecharge(event, first, second)) return; + + this.handleCombine(event, first, second, result); + + this.plugin.runTask(task -> { + ItemStack updated = event.getResult(); + if (updated == null || updated.getType().isAir()) return; + + EnchantUtils.updateDisplay(updated); + inventory.setItem(2, updated); + }); } - private boolean handleRename(@NotNull PrepareAnvilEvent event, @NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) { - if (!(second.getType().isAir() || second.getType() != first.getType() && second.getType() != Material.ENCHANTED_BOOK)) { - return false; - } - if (result.getType() != first.getType()) { - return false; - } - ItemStack result2 = new ItemStack(result); - EnchantUtils.getExcellents(first).forEach((hasEnch, hasLevel) -> EnchantUtils.add(result2, hasEnch.getBackend(), hasLevel, true)); - EnchantUtils.updateDisplay(result2); - event.setResult(result2); + /*private boolean handleRename(@NotNull PrepareAnvilEvent event, @NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) { + if (!(second.getType().isAir() || second.getType() != first.getType() && !EnchantUtils.isEnchantedBook(second))) return false; + if (result.getType() != first.getType()) return false; + + ItemStack renamed = new ItemStack(result); + EnchantUtils.getCustomEnchantments(first).forEach((hasEnch, hasLevel) -> EnchantUtils.add(renamed, hasEnch.getEnchantment(), hasLevel, true)); + EnchantUtils.updateDisplay(renamed); + + event.setResult(renamed); return true; - } + }*/ - private boolean handleRecharge(@NotNull PrepareAnvilEvent event, @NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) { - int count; - if (second.getType().isAir()) { - return false; - } - HashMap chargable = new HashMap(); - EnchantUtils.getExcellents(first).forEach((enchant, level) -> { - if (enchant.isChargesEnabled() && enchant.isChargesFuel(second) && !enchant.isFullOfCharges(first)) { - chargable.put(enchant, level); + private boolean handleRecharge(@NotNull PrepareAnvilEvent event, @NotNull ItemStack first, @NotNull ItemStack second) { + if (second.getType().isAir()) return false; + + Map chargable = new HashMap<>(); + EnchantUtils.getCustomEnchantments(first).forEach((data, level) -> { + if (data.isChargesEnabled() && data.isChargesFuel(second) && !data.isFullOfCharges(first)) { + chargable.put(data, level); } }); - if (chargable.isEmpty()) { - return false; + if (chargable.isEmpty()) return false; + + int count; + ItemStack recharged = new ItemStack(first); + for (count = 0; count < second.getAmount() && !chargable.keySet().stream().allMatch(data -> data.isFullOfCharges(recharged)); ++count) { + chargable.forEach((enchant, level) -> enchant.fuelCharges(recharged, level)); } - ItemStack result2 = new ItemStack(first); - for (count = 0; count < second.getAmount() && !chargable.keySet().stream().allMatch(en -> en.isFullOfCharges(result2)); ++count) { - chargable.forEach((enchant, level) -> EnchantUtils.rechargeCharges(result2, enchant, level)); - } - PDCUtil.set(result2, RECHARGED, count); - EnchantUtils.updateDisplay(result2); - event.setResult(result2); + + PDCUtil.set(recharged, Keys.itemRecharged, count); + EnchantUtils.updateDisplay(recharged); + event.setResult(recharged); + this.plugin.runTask(task -> event.getInventory().setRepairCost(chargable.size())); return true; } - private boolean handleEnchantMerging(@NotNull PrepareAnvilEvent event, @NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) { - if (second.getType().isAir() || second.getAmount() > 1 || !EnchantUtils.isEnchantable(second)) { - return false; + private boolean handleCombine(@NotNull PrepareAnvilEvent event, @NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) { + ItemStack merged = new ItemStack(result.getType().isAir() ? first : result); + + Map chargesMap = new HashMap<>(); + EnchantUtils.getCustomEnchantments(result).forEach((data, level) -> { + if (!data.isChargesEnabled()) return; + + int chargesFirst = data.getCharges(first); + int chargesSecond = data.getCharges(second); + + chargesMap.put(data, chargesFirst + chargesSecond); + data.setCharges(merged, level, chargesFirst + chargesSecond); + }); + if (!chargesMap.isEmpty()) { + event.setResult(merged); + return true; } - if (first.getType() == Material.ENCHANTED_BOOK && second.getType() != first.getType()) { - return false; - } - ItemStack result2 = new ItemStack(result.getType().isAir() ? first : result); - Map enchantments = EnchantUtils.getExcellents(first); - HashMap charges = new HashMap(enchantments.keySet().stream().collect(Collectors.toMap(k -> k, v -> v.getCharges(first)))); + return false; + + /* + if (second.getType().isAir() || second.getAmount() > 1 || !EnchantUtils.isEnchantable(second)) return false; + if (EnchantUtils.isEnchantedBook(first) && second.getType() != first.getType()) return false; + Map firstEnchants = EnchantUtils.getCustomEnchantments(first); + //Map secondEnchants = EnchantUtils.getCustomEnchantments(second); + Map charges = new HashMap<>(firstEnchants.keySet().stream().collect(Collectors.toMap(k -> k, v -> v.getCharges(first)))); AtomicInteger repairCost = new AtomicInteger(event.getInventory().getRepairCost()); - if (second.getType() == Material.ENCHANTED_BOOK || second.getType() == first.getType()) { - EnchantUtils.getExcellents(second).forEach((enchant, level) -> { - enchantments.merge(enchant, level, (oldLvl, newLvl) -> oldLvl.equals(newLvl) ? Math.min(enchant.getMaxMergeLevel(), oldLvl + 1) : Math.max(oldLvl, newLvl)); - charges.merge(enchant, enchant.getCharges(second), Integer::sum); + + if (EnchantUtils.isEnchantedBook(second) || second.getType() == first.getType()) { + EnchantUtils.getCustomEnchantments(second).forEach((data, level) -> { + int maxMergeLevel = data.getMaxMergeLevel() < 0 ? data.getMaxLevel() : data.getMaxMergeLevel(); + + firstEnchants.merge(data, level, (oldLvl, newLvl) -> oldLvl.equals(newLvl) ? Math.min(maxMergeLevel, oldLvl + 1) : Math.max(oldLvl, newLvl)); + charges.merge(data, data.getCharges(second), Integer::sum); }); } - enchantments.forEach((enchant, level) -> { - if (EnchantUtils.add(result2, enchant.getBackend(), level, false)) { - repairCost.addAndGet(enchant.getAnvilMergeCost(level)); - EnchantUtils.setCharges(result2, enchant, level, charges.getOrDefault(enchant, 0)); + + firstEnchants.forEach((enchantmentData, level) -> { + if (EnchantUtils.add(merged, enchantmentData.getEnchantment(), level, false)) { + repairCost.addAndGet(enchantmentData.getAnvilMergeCost(level)); + enchantmentData.setCharges(merged, level, charges.getOrDefault(enchantmentData, 0)); } }); - if (first.equals(result2)) { - return false; - } - EnchantUtils.updateDisplay(result2); - event.setResult(result2); + + if (first.equals(merged)) return false; + + EnchantUtils.updateDisplay(merged); + event.setResult(merged); this.plugin.runTask(task -> event.getInventory().setRepairCost(repairCost.get())); - return true; + return true;*/ } - @EventHandler(priority=EventPriority.NORMAL) + @EventHandler(priority = EventPriority.NORMAL) public void onClickAnvil(InventoryClickEvent event) { Inventory inventory = event.getInventory(); - if (!(inventory instanceof AnvilInventory inventory2)) { - return; - } - if (event.getRawSlot() != 2) { - return; - } + if (!(inventory instanceof AnvilInventory anvilInventory)) return; + if (event.getRawSlot() != 2) return; + ItemStack item = event.getCurrentItem(); - if (item == null) { - return; - } - int count = PDCUtil.getInt(item, RECHARGED).orElse(0); - if (count == 0) { - return; - } - Player player = (Player)event.getWhoClicked(); - if (player.getLevel() < inventory2.getRepairCost()) { - return; - } - player.setLevel(player.getLevel() - inventory2.getRepairCost()); - PDCUtil.remove(item, RECHARGED); + if (item == null) return; + + int count = PDCUtil.getInt(item, Keys.itemRecharged).orElse(0); + if (count == 0) return; + + Player player = (Player) event.getWhoClicked(); + if (player.getLevel() < anvilInventory.getRepairCost()) return; + + player.setLevel(player.getLevel() - anvilInventory.getRepairCost()); + PDCUtil.remove(item, Keys.itemRecharged); event.getView().setCursor(item); event.setCancelled(false); + UniSound.of(Sound.BLOCK_ENCHANTMENT_TABLE_USE).play(player); - ItemStack second = inventory2.getItem(1); + + ItemStack second = anvilInventory.getItem(1); if (second != null && !second.getType().isAir()) { second.setAmount(second.getAmount() - count); } - inventory2.setItem(0, null); - inventory2.setItem(2, null); + + anvilInventory.setItem(0, null); + anvilInventory.setItem(2, null); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantGenericListener.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantGenericListener.java index 7b6f403..34dea08 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantGenericListener.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantGenericListener.java @@ -1,63 +1,58 @@ package su.nightexpress.excellentenchants.enchantment.listener; -import org.bukkit.World; -import org.bukkit.block.Chest; -import org.bukkit.entity.*; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.enchantment.EnchantItemEvent; -import org.bukkit.event.entity.*; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryType; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.event.world.LootGenerateEvent; -import org.bukkit.inventory.*; -import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.Version; -import su.nexmedia.engine.api.manager.AbstractListener; -import su.nexmedia.engine.utils.EngineUtils; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.enchantment.EnchantManager; -import su.nightexpress.excellentenchants.enchantment.EnchantPopulator; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; -import su.nightexpress.excellentenchants.hook.HookId; -import su.nightexpress.excellentenchants.hook.impl.MythicMobsHook; +import su.nightexpress.nightcore.manager.AbstractListener; -import java.util.HashMap; -import java.util.Map; +public class EnchantGenericListener extends AbstractListener { -public class EnchantGenericListener extends AbstractListener { + //private final EnchantManager enchantManager; - public EnchantGenericListener(@NotNull EnchantManager enchantManager) { - super(enchantManager.plugin()); + public EnchantGenericListener(@NotNull ExcellentEnchantsPlugin plugin, @NotNull EnchantManager enchantManager) { + super(plugin); + //this.enchantManager = enchantManager; + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onCreatureSpawn(CreatureSpawnEvent event) { + EnchantUtils.setSpawnReason(event.getEntity(), event.getSpawnReason()); } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onEnchantProjectileShoot(EntityShootBowEvent event) { + public void onEnchantedProjectileShoot(EntityShootBowEvent event) { if (event.getProjectile() instanceof Projectile projectile) { - EnchantUtils.setSourceWeapon(projectile, event.getBow()); + EnchantUtils.addEnchantedProjectile(projectile, event.getBow()); } } @EventHandler(priority = EventPriority.MONITOR) - public void onEnchantProjectileLand(ProjectileHitEvent event) { + public void onEnchantedProjectileLand(ProjectileHitEvent event) { this.plugin.runTask(task -> { - EnchantUtils.removeSourceWeapon(event.getEntity()); + EnchantUtils.removeEnchantedProjectile(event.getEntity()); }); } - // --------------------------------------------------------------- - // Update enchantment lore after grindstone - // --------------------------------------------------------------- @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantUpdateGrindstoneClick(InventoryClickEvent event) { + public void onEnchantDisplayUpdateGrindstoneClick(InventoryClickEvent event) { Inventory inventory = event.getInventory(); if (inventory.getType() != InventoryType.GRINDSTONE) return; if (event.getRawSlot() == 2) return; @@ -66,7 +61,7 @@ public class EnchantGenericListener extends AbstractListener } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantUpdateGrindstoneDrag(InventoryDragEvent event) { + public void onEnchantDisplayUpdateGrindstoneDrag(InventoryDragEvent event) { Inventory inventory = event.getInventory(); if (inventory.getType() != InventoryType.GRINDSTONE) return; @@ -74,31 +69,17 @@ public class EnchantGenericListener extends AbstractListener } private void updateGrindstone(@NotNull Inventory inventory) { - this.plugin.getServer().getScheduler().runTask(plugin, () -> { + this.plugin.runTask(task -> { ItemStack result = inventory.getItem(2); if (result == null || result.getType().isAir()) return; - // No NMS registration for 1.18.2, server does not know they are curses. - if (Version.isBehind(Version.V1_19_R3) && !Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) { - Map curses = new HashMap<>(); - for (int slot = 0; slot < 2; slot++) { - ItemStack source = inventory.getItem(slot); - if (source == null || source.getType().isAir()) continue; - - curses.putAll(EnchantUtils.getExcellents(source)); - } - curses.entrySet().removeIf(entry -> !entry.getKey().isCurse()); - curses.forEach((excellentEnchant, level) -> { - EnchantUtils.add(result, excellentEnchant.getBackend(), level, true); - }); - } EnchantUtils.updateDisplay(result); }); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantUpdatePickup(EntityPickupItemEvent event) { - if (!(event.getEntity() instanceof Player player)) return; + public void onEnchantDisplayUpdatePickup(EntityPickupItemEvent event) { + if (!(event.getEntity() instanceof Player)) return; Item item = event.getItem(); ItemStack itemStack = item.getItemStack(); @@ -107,146 +88,23 @@ public class EnchantGenericListener extends AbstractListener } } - // --------------------------------------------------------------- - // Handle Enchanting Table - // --------------------------------------------------------------- - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onEnchantPopulateEnchantingTable(final EnchantItemEvent event) { - ItemStack target = event.getItem(); - World world = event.getEnchanter().getWorld(); + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEnchantDisplayUpdateEnchanting(EnchantItemEvent event) { + this.plugin.runTask(task -> { + Inventory inventory = event.getInventory(); - if (!Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) { - EnchantPopulator populator = this.plugin.createPopulator(target, ObtainType.ENCHANTING) - .withWorld(world) - .withLevelGenerator(enchant -> enchant.getLevelByEnchantCost(event.getExpLevelCost())) - .withDefaultPopulation(event.getEnchantsToAdd()); - - event.getEnchantsToAdd().putAll(populator.createPopulation()); - } - - plugin.getServer().getScheduler().runTask(plugin, () -> { - ItemStack result = event.getInventory().getItem(0); + ItemStack result = inventory.getItem(0); if (result == null) return; - // Fix enchantments for Enchant Books. - // Enchants are not added on book because they do not exists in NMS. - // Server gets enchants from NMS to apply it on Book NBT tags. - if (Version.isBehind(Version.V1_19_R3)) { - ItemMeta meta = result.getItemMeta(); - if (meta instanceof EnchantmentStorageMeta storageMeta) { - event.getEnchantsToAdd().forEach((enchantment, level) -> { - if (!storageMeta.hasStoredEnchant(enchantment)) { - storageMeta.addStoredEnchant(enchantment, level, true); - } - }); - result.setItemMeta(storageMeta); - } - } - event.getEnchantsToAdd().forEach((enchantment, level) -> { - ExcellentEnchant enchant = EnchantRegistry.getByKey(enchantment.getKey()); + EnchantmentData enchant = EnchantRegistry.getByKey(enchantment.getKey()); if (enchant != null) { - EnchantUtils.restoreCharges(result, enchant, level); + enchant.restoreCharges(result, level); } }); EnchantUtils.updateDisplay(result); - event.getInventory().setItem(0, result); + inventory.setItem(0, result); }); } - - // --------------------------------------------------------------- - // Adding Enchants to Villagers - // --------------------------------------------------------------- - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantPopulateVillagerAcquire(VillagerAcquireTradeEvent event) { - if (Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) return; - - MerchantRecipe origin = event.getRecipe(); - ItemStack result = origin.getResult(); - if (!EnchantUtils.isEnchantable(result)) return; - - EnchantPopulator populator = this.plugin.createPopulator(result, ObtainType.VILLAGER) - .withWorld(event.getEntity().getWorld()); - if (!populator.populate()) return; - - int uses = origin.getUses(); - int maxUses = origin.getMaxUses(); - boolean expReward = origin.hasExperienceReward(); - int villagerExperience = origin.getVillagerExperience(); - float priceMultiplier = origin.getPriceMultiplier(); - int demand = origin.getDemand(); - int specialPrice = origin.getSpecialPrice(); - - MerchantRecipe recipe = new MerchantRecipe(result, uses, maxUses, expReward, villagerExperience, - priceMultiplier, demand, specialPrice); - recipe.setIngredients(origin.getIngredients()); - event.setRecipe(recipe); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantPopulateLoot(LootGenerateEvent event) { - if (Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) return; - if (Config.getObtainSettings(ObtainType.LOOT_GENERATION).isEmpty()) return; - - Entity entity = event.getEntity(); - InventoryHolder holder = event.getInventoryHolder(); - World world = event.getWorld(); - - if (entity instanceof Minecart || holder instanceof Chest) { - event.getLoot().forEach(item -> { - if (item != null && EnchantUtils.isEnchantable(item)) { - this.plugin.createPopulator(item, ObtainType.LOOT_GENERATION) - .withWorld(world) - .populate(); - } - }); - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantPopulateFishing(PlayerFishEvent event) { - if (Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) return; - if (Config.getObtainSettings(ObtainType.FISHING).isEmpty()) return; - if (event.getState() != PlayerFishEvent.State.CAUGHT_FISH) return; - if (!(event.getCaught() instanceof Item item)) return; - - ItemStack itemStack = item.getItemStack(); - World world = item.getWorld(); - if (EnchantUtils.isEnchantable(itemStack)) { - this.plugin.createPopulator(itemStack, ObtainType.FISHING).withWorld(world).populate(); - } - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onEnchantPopulateSpawn(CreatureSpawnEvent event) { - if (Config.ENCHANTMENTS_INTERNAL_HANDLER.get()) return; - - //if (Config.getObtainSettings(ObtainType.MOB_SPAWNING).isEmpty()) return; - LivingEntity entity = event.getEntity(); - if (entity.getType() == EntityType.ARMOR_STAND) return; - if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.DISPENSE_EGG) return; - if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER_EGG) return; - if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER) return; - - this.plugin.runTaskLater(task -> { - EntityEquipment equipment = entity.getEquipment(); - if (equipment == null) return; - - World world = entity.getWorld(); - boolean isMythic = EngineUtils.hasPlugin(HookId.MYTHIC_MOBS) && MythicMobsHook.isMythicMob(entity); - boolean doPopulation = Config.getObtainSettings(ObtainType.MOB_SPAWNING).isPresent() && !isMythic; - - for (EquipmentSlot slot : EquipmentSlot.values()) { - ItemStack item = equipment.getItem(slot); - if (EnchantUtils.isEnchantable(item)) { - if (doPopulation) { - this.plugin.createPopulator(item, ObtainType.MOB_SPAWNING).withWorld(world).populate(); - } - EnchantUtils.getExcellents(item).forEach((enchant, level) -> EnchantUtils.restoreCharges(item, enchant, level)); - equipment.setItem(slot, item); - } - } - }, 40L); - } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantPopulationListener.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantPopulationListener.java new file mode 100644 index 0000000..62010e0 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/listener/EnchantPopulationListener.java @@ -0,0 +1,131 @@ +package su.nightexpress.excellentenchants.enchantment.listener; + +import org.bukkit.World; +import org.bukkit.block.Chest; +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.enchantment.EnchantItemEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.VillagerAcquireTradeEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.event.world.LootGenerateEvent; +import org.bukkit.inventory.*; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.enchantment.EnchantPopulator; +import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.excellentenchants.hook.HookId; +import su.nightexpress.excellentenchants.hook.impl.MythicMobsHook; +import su.nightexpress.nightcore.manager.AbstractListener; +import su.nightexpress.nightcore.util.Plugins; + +public class EnchantPopulationListener extends AbstractListener { + + public EnchantPopulationListener(@NotNull ExcellentEnchantsPlugin plugin) { + super(plugin); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPopulateEnchantingTable(EnchantItemEvent event) { + ItemStack target = event.getItem(); + World world = event.getEnchanter().getWorld(); + + EnchantPopulator populator = this.plugin.createPopulator(target, DistributionWay.ENCHANTING) + .withWorld(world) + .withLevelGenerator((data, distribution) -> distribution.getLevelByEnchantCost(event.getExpLevelCost())) + .withDefaultPopulation(event.getEnchantsToAdd()); + + event.getEnchantsToAdd().putAll(populator.createPopulation()); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPopulateVillagerAcquire(VillagerAcquireTradeEvent event) { + if (Config.getDistributionWaySettings(DistributionWay.VILLAGER).isEmpty()) return; + + MerchantRecipe origin = event.getRecipe(); + ItemStack result = origin.getResult(); + if (!EnchantUtils.isEnchantable(result)) return; + + EnchantPopulator populator = this.plugin.createPopulator(result, DistributionWay.VILLAGER) + .withWorld(event.getEntity().getWorld()); + if (!populator.populate()) return; + + int uses = origin.getUses(); + int maxUses = origin.getMaxUses(); + boolean expReward = origin.hasExperienceReward(); + int villagerExperience = origin.getVillagerExperience(); + float priceMultiplier = origin.getPriceMultiplier(); + int demand = origin.getDemand(); + int specialPrice = origin.getSpecialPrice(); + + MerchantRecipe recipe = new MerchantRecipe(result, uses, maxUses, expReward, villagerExperience, + priceMultiplier, demand, specialPrice); + recipe.setIngredients(origin.getIngredients()); + event.setRecipe(recipe); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPopulateLoot(LootGenerateEvent event) { + if (Config.getDistributionWaySettings(DistributionWay.LOOT_GENERATION).isEmpty()) return; + + Entity entity = event.getEntity(); + InventoryHolder holder = event.getInventoryHolder(); + World world = event.getWorld(); + + if (entity instanceof Minecart || holder instanceof Chest) { + event.getLoot().forEach(item -> { + if (item != null && EnchantUtils.isEnchantable(item)) { + this.plugin.createPopulator(item, DistributionWay.LOOT_GENERATION) + .withWorld(world) + .withCondition((data, customDistribution) -> customDistribution.isGoodLootTable(event.getLootTable())) + .populate(); + } + }); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPopulateFishing(PlayerFishEvent event) { + if (Config.getDistributionWaySettings(DistributionWay.FISHING).isEmpty()) return; + if (event.getState() != PlayerFishEvent.State.CAUGHT_FISH) return; + if (!(event.getCaught() instanceof Item item)) return; + + ItemStack itemStack = item.getItemStack(); + World world = item.getWorld(); + if (EnchantUtils.isEnchantable(itemStack)) { + this.plugin.createPopulator(itemStack, DistributionWay.FISHING).withWorld(world).populate(); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPopulateSpawn(CreatureSpawnEvent event) { + LivingEntity entity = event.getEntity(); + if (entity.getType() == EntityType.ARMOR_STAND) return; + if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.DISPENSE_EGG) return; + if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER_EGG) return; + if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.SPAWNER) return; + + this.plugin.runTaskLater(task -> { + EntityEquipment equipment = entity.getEquipment(); + if (equipment == null) return; + + World world = entity.getWorld(); + boolean isMythic = Plugins.isLoaded(HookId.MYTHIC_MOBS) && MythicMobsHook.isMythicMob(entity); + boolean doPopulation = Config.getDistributionWaySettings(DistributionWay.MOB_EQUIPMENT).isPresent() && !isMythic; + + for (EquipmentSlot slot : EquipmentSlot.values()) { + ItemStack item = equipment.getItem(slot); + if (EnchantUtils.isEnchantable(item)) { + if (doPopulation) { + this.plugin.createPopulator(item, DistributionWay.MOB_EQUIPMENT).withWorld(world).populate(); + } + EnchantUtils.getCustomEnchantments(item).forEach((enchant, level) -> enchant.restoreCharges(item, level)); + equipment.setItem(slot, item); + } + } + }, 40L); // меньше недостаточно + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/menu/EnchantmentsListMenu.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/menu/EnchantmentsListMenu.java index 4eb38ae..ebc6d47 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/menu/EnchantmentsListMenu.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/menu/EnchantmentsListMenu.java @@ -1,74 +1,43 @@ -/* - * Decompiled with CFR 0.151. - * - * Could not load the following classes: - * org.bukkit.Material - * org.bukkit.NamespacedKey - * org.bukkit.entity.Player - * org.bukkit.event.inventory.InventoryType - * org.bukkit.inventory.ItemStack - * org.bukkit.plugin.Plugin - * org.jetbrains.annotations.NotNull - * su.nexmedia.engine.NexPlugin - * su.nexmedia.engine.api.config.JOption - * su.nexmedia.engine.api.config.JYML - * su.nexmedia.engine.api.menu.AutoPaged - * su.nexmedia.engine.api.menu.MenuItemType - * su.nexmedia.engine.api.menu.click.ClickHandler - * su.nexmedia.engine.api.menu.click.ItemClick - * su.nexmedia.engine.api.menu.impl.ConfigMenu - * su.nexmedia.engine.api.menu.impl.Menu - * su.nexmedia.engine.api.menu.impl.MenuOptions - * su.nexmedia.engine.api.menu.impl.MenuViewer - * su.nexmedia.engine.api.menu.item.MenuItem - * su.nexmedia.engine.api.placeholder.PlaceholderMap - * su.nexmedia.engine.utils.Colorizer - * su.nexmedia.engine.utils.ItemReplacer - * su.nexmedia.engine.utils.ItemUtil - * su.nexmedia.engine.utils.PDCUtil - */ package su.nightexpress.excellentenchants.enchantment.menu; import org.bukkit.Material; import org.bukkit.NamespacedKey; -import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.api.editor.EditorLocales; -import su.nexmedia.engine.api.menu.AutoPaged; -import su.nexmedia.engine.api.menu.MenuItemType; -import su.nexmedia.engine.api.menu.click.ClickHandler; -import su.nexmedia.engine.api.menu.click.ItemClick; -import su.nexmedia.engine.api.menu.impl.ConfigMenu; -import su.nexmedia.engine.api.menu.impl.MenuOptions; -import su.nexmedia.engine.api.menu.impl.MenuViewer; -import su.nexmedia.engine.api.menu.item.MenuItem; -import su.nexmedia.engine.api.placeholder.PlaceholderMap; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.ItemReplacer; -import su.nexmedia.engine.utils.ItemUtil; -import su.nexmedia.engine.utils.PDCUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.DistributionWay; +import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.enchantment.data.CustomDistribution; import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.nightcore.config.ConfigValue; +import su.nightexpress.nightcore.config.FileConfig; +import su.nightexpress.nightcore.core.CoreLang; +import su.nightexpress.nightcore.menu.MenuOptions; +import su.nightexpress.nightcore.menu.MenuViewer; +import su.nightexpress.nightcore.menu.api.AutoFill; +import su.nightexpress.nightcore.menu.api.AutoFilled; +import su.nightexpress.nightcore.menu.impl.ConfigMenu; +import su.nightexpress.nightcore.menu.item.ItemHandler; +import su.nightexpress.nightcore.menu.item.MenuItem; +import su.nightexpress.nightcore.util.*; import java.util.*; import java.util.function.Predicate; import java.util.stream.IntStream; -import static su.nexmedia.engine.utils.Colors2.*; import static su.nightexpress.excellentenchants.Placeholders.*; +import static su.nightexpress.nightcore.util.text.tag.Tags.*; -public class EnchantmentsListMenu extends ConfigMenu implements AutoPaged { +public class EnchantmentsListMenu extends ConfigMenu implements AutoFilled { + + private static final String FILE_NAME = "enchants.yml"; - private static final String FILE = "enchants.yml"; private static final String PLACEHOLDER_CONFLICTS = "%conflicts%"; - private static final String PLACEHOLDER_CHARGES = "%charges%"; + private static final String PLACEHOLDER_CHARGES = "%charges%"; private static final String PLACEHOLDER_OBTAINING = "%obtaining%"; private final NamespacedKey keyLevel; @@ -82,11 +51,11 @@ public class EnchantmentsListMenu extends ConfigMenu implemen private List enchantLoreObtaining; private int[] enchantSlots; - public EnchantmentsListMenu(@NotNull ExcellentEnchants plugin) { - super(plugin, new JYML(plugin.getDataFolder() + "/menu/", FILE)); + public EnchantmentsListMenu(@NotNull ExcellentEnchantsPlugin plugin) { + super(plugin, FileConfig.loadOrExtract(plugin, Config.DIR_MENU, FILE_NAME)); this.keyLevel = new NamespacedKey(plugin, "list_display_level"); this.iconCache = new HashMap<>(); - this.registerHandler(MenuItemType.class).addClick(MenuItemType.CLOSE, ClickHandler.forClose(this)).addClick(MenuItemType.PAGE_NEXT, ClickHandler.forNextPage(this)).addClick(MenuItemType.PAGE_PREVIOUS, ClickHandler.forPreviousPage(this)); + this.load(); } @@ -95,112 +64,123 @@ public class EnchantmentsListMenu extends ConfigMenu implemen this.iconCache.clear(); } - public boolean isCodeCreation() { - return true; - } - + @Override protected void loadAdditional() { - this.enchantIcon = JOption.create("Enchantment.Icon", new ItemStack(Material.ENCHANTED_BOOK)).read(this.cfg); - this.enchantName = JOption.create("Enchantment.Name", ENCHANTMENT_NAME_FORMATTED).read(this.cfg); - this.enchantLoreMain = JOption.create("Enchantment.Lore.Main", + this.enchantIcon = ConfigValue.create("Enchantment.Icon", new ItemStack(Material.ENCHANTED_BOOK)).read(this.cfg); + + this.enchantName = ConfigValue.create("Enchantment.Name", ENCHANTMENT_NAME_FORMATTED).read(this.cfg); + + this.enchantLoreMain = ConfigValue.create("Enchantment.Lore.Main", Arrays.asList( - ENCHANTMENT_DESCRIPTION, - DARK_GRAY + "(click to switch level)", "", - LIGHT_YELLOW + BOLD + "Info:", - LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Tier: " + LIGHT_YELLOW + ENCHANTMENT_TIER, - LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Applies to: " + LIGHT_YELLOW + ENCHANTMENT_FIT_ITEM_TYPES, - LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Levels: " + LIGHT_YELLOW + ENCHANTMENT_LEVEL_MIN + LIGHT_GRAY + " - " + LIGHT_YELLOW + ENCHANTMENT_LEVEL_MAX, - PLACEHOLDER_CHARGES, PLACEHOLDER_CONFLICTS, PLACEHOLDER_OBTAINING + ENCHANTMENT_RARITY, + "", + ENCHANTMENT_DESCRIPTION_REPLACED, + DARK_GRAY.enclose("(click to switch levels)"), + "", + LIGHT_YELLOW.enclose(BOLD.enclose("Info:")), + LIGHT_YELLOW.enclose("▪ " + LIGHT_GRAY.enclose("Applies to: ") + ENCHANTMENT_FIT_ITEM_TYPES), + LIGHT_YELLOW.enclose("▪ " + LIGHT_GRAY.enclose("Levels: ") + ENCHANTMENT_LEVEL_MIN + LIGHT_GRAY.enclose(" - ") + ENCHANTMENT_LEVEL_MAX), + PLACEHOLDER_CHARGES, + PLACEHOLDER_CONFLICTS, + PLACEHOLDER_OBTAINING )).read(this.cfg); - this.enchantLoreConflicts = JOption.create("Enchantment.Lore.Conflicts", - Arrays.asList( - "", LIGHT_RED + BOLD + "Conflicts:", - LIGHT_RED + "✘ " + LIGHT_GRAY + GENERIC_NAME - )).read(this.cfg); - - this.enchantLoreCharges = JOption.create("Enchantment.Lore.Charges", + this.enchantLoreConflicts = ConfigValue.create("Enchantment.Lore.Conflicts", List.of( - LIGHT_YELLOW + "▪ " + LIGHT_GRAY + "Charges: " + LIGHT_YELLOW + ENCHANTMENT_CHARGES_MAX_AMOUNT + "⚡" + LIGHT_GRAY + " (" + WHITE + ENCHANTMENT_CHARGES_FUEL_ITEM + LIGHT_GRAY + ")") + "", + LIGHT_RED.enclose(BOLD.enclose("Conflicts:")), + LIGHT_RED.enclose("✘ ") + LIGHT_GRAY.enclose(GENERIC_NAME) + )).read(this.cfg); + + this.enchantLoreCharges = ConfigValue.create("Enchantment.Lore.Charges", + List.of( + LIGHT_YELLOW.enclose("▪ " + LIGHT_GRAY.enclose("Charges: ") + GENERIC_AMOUNT + "⚡" + LIGHT_GRAY.enclose(" (" + WHITE.enclose(GENERIC_ITEM) + ")"))) ).read(this.cfg); - this.enchantLoreObtaining = JOption.create("Enchantment.Lore.Obtaining", - Arrays.asList("", LIGHT_GREEN + BOLD + "Obtaining:", LIGHT_GREEN + "✔ " + LIGHT_GRAY + GENERIC_TYPE)).read(this.cfg); + this.enchantLoreObtaining = ConfigValue.create("Enchantment.Lore.Obtaining", + List.of( + "", + LIGHT_GREEN.enclose(BOLD.enclose("Obtaining:")), + LIGHT_GREEN.enclose("✔ ") + LIGHT_GRAY.enclose(GENERIC_TYPE)) + ).read(this.cfg); - this.enchantSlots = new JOption("Enchantment.Slots", (cfg, path, def) -> cfg.getIntArray(path), () -> IntStream.range(0, 27).toArray()).setWriter(JYML::setIntArray).read(this.cfg); + this.enchantSlots = ConfigValue.create("Enchantment.Slots", IntStream.range(0, 27).toArray()).read(this.cfg); } @NotNull protected MenuOptions createDefaultOptions() { - return new MenuOptions("#6c6c62&lCustom Enchants", 36, InventoryType.CHEST); + return new MenuOptions(BLACK.enclose("Custom Enchantments"), 36, InventoryType.CHEST); } @NotNull protected List createDefaultItems() { - ArrayList list = new ArrayList<>(); - ItemStack nextPageStack = ItemUtil.createCustomHead("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMyY2E2NjA1NmI3Mjg2M2U5OGY3ZjMyYmQ3ZDk0YzdhMGQ3OTZhZjY5MWM5YWMzYTkxMzYzMzEzNTIyODhmOSJ9fX0="); - ItemUtil.mapMeta(nextPageStack, meta -> meta.setDisplayName(EditorLocales.NEXT_PAGE.getLocalizedName())); - ItemStack prevPageStack = ItemUtil.createCustomHead("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5NzFkZDg4MWRiYWY0ZmQ2YmNhYTkzNjE0NDkzYzYxMmY4Njk2NDFlZDU5ZDFjOTM2M2EzNjY2YTVmYTYifX19"); - ItemUtil.mapMeta(prevPageStack, meta -> meta.setDisplayName(EditorLocales.PREVIOUS_PAGE.getLocalizedName())); - list.add(new MenuItem(nextPageStack).setSlots(new int[]{35}).setType(MenuItemType.PAGE_NEXT).setPriority(5)); - list.add(new MenuItem(prevPageStack).setSlots(new int[]{27}).setType(MenuItemType.PAGE_PREVIOUS).setPriority(5)); + List list = new ArrayList<>(); + + ItemStack nextPageStack = ItemUtil.getSkinHead(SKIN_ARROW_RIGHT); + ItemUtil.editMeta(nextPageStack, meta -> meta.setDisplayName(CoreLang.EDITOR_ITEM_NEXT_PAGE.getLocalizedName())); + + ItemStack prevPageStack = ItemUtil.getSkinHead(SKIN_ARROW_LEFT); + ItemUtil.editMeta(prevPageStack, meta -> meta.setDisplayName(CoreLang.EDITOR_ITEM_PREVIOUS_PAGE.getLocalizedName())); + + list.add(new MenuItem(nextPageStack).setSlots(35).setHandler(ItemHandler.forNextPage(this)).setPriority(5)); + list.add(new MenuItem(prevPageStack).setSlots(27).setHandler(ItemHandler.forPreviousPage(this)).setPriority(5)); + return list; } + @Override public void onPrepare(@NotNull MenuViewer viewer, @NotNull MenuOptions options) { - super.onPrepare(viewer, options); - this.getItemsForPage(viewer).forEach(this::addItem); + this.autoFill(viewer); } - public int[] getObjectSlots() { - return this.enchantSlots; + @Override + protected void onReady(@NotNull MenuViewer viewer, @NotNull Inventory inventory) { + } - @NotNull - public List getObjects(@NotNull Player player) { - return new ArrayList<>(EnchantRegistry.getRegistered().stream().filter(Predicate.not(enchant -> enchant.getDefaults().isHiddenFromList())).sorted(Comparator.comparing(e -> Colorizer.restrip(e.getDisplayName()))).toList()); - } + @Override + public void onAutoFill(@NotNull MenuViewer viewer, @NotNull AutoFill autoFill) { + autoFill.setSlots(this.enchantSlots); + autoFill.setItems(EnchantRegistry.getRegistered().stream() + .filter(Predicate.not(EnchantmentData::isHiddenFromList)) + .sorted(Comparator.comparing(data -> Colorizer.restrip(data.getName()))) + .toList() + ); + autoFill.setItemCreator(enchantmentData -> this.getEnchantIcon(enchantmentData, 1)); + autoFill.setClickAction(enchantmentData -> (viewer1, event) -> { + if (!event.isLeftClick()) return; - @NotNull - public ItemStack getObjectStack(@NotNull Player player, @NotNull ExcellentEnchant enchant) { - return this.getEnchantIcon(enchant, 1); - } + ItemStack currentItem = event.getCurrentItem(); + if (currentItem == null) return; - @NotNull - public ItemClick getObjectClick(@NotNull ExcellentEnchant enchant) { - return (viewer, event) -> { - if (!event.isLeftClick()) { - return; - } - ItemStack itemClick = event.getCurrentItem(); - if (itemClick == null) { - return; - } - int levelHas = PDCUtil.getInt(itemClick, this.keyLevel).orElse(0); + int levelHas = PDCUtil.getInt(currentItem, this.keyLevel).orElse(0); if (levelHas == 0) { - levelHas = enchant.getStartLevel(); + levelHas = enchantmentData.getMinLevel(); } - if (++levelHas > enchant.getMaxLevel()) { - levelHas = enchant.getStartLevel(); + if (++levelHas > enchantmentData.getMaxLevel()) { + levelHas = enchantmentData.getMinLevel(); } - itemClick = this.getEnchantIcon(enchant, levelHas); - PDCUtil.set(itemClick, this.keyLevel, levelHas); - event.setCurrentItem(itemClick); - }; + currentItem = this.getEnchantIcon(enchantmentData, levelHas); + PDCUtil.set(currentItem, this.keyLevel, levelHas); + event.setCurrentItem(currentItem); + }); } - private ItemStack getEnchantIcon(@NotNull ExcellentEnchant enchant, int level) { + private ItemStack getEnchantIcon(@NotNull EnchantmentData enchant, int level) { return this.iconCache.computeIfAbsent(enchant.getId(), k -> new HashMap<>()).computeIfAbsent(level, k -> this.buildEnchantIcon(enchant, level)); } @NotNull - private ItemStack buildEnchantIcon(@NotNull ExcellentEnchant enchant, int level) { + private ItemStack buildEnchantIcon(@NotNull EnchantmentData enchant, int level) { ItemStack icon = new ItemStack(this.enchantIcon); + List conflicts = new ArrayList<>(); if (enchant.hasConflicts()) { for (String line : this.enchantLoreConflicts) { - if (line.contains("%name%")) { - enchant.getConflicts().stream().map(EnchantUtils::getLocalized).filter(Objects::nonNull).forEach(conf -> conflicts.add(line.replace("%name%", conf))); + if (line.contains(GENERIC_NAME)) { + enchant.getConflicts().stream() + .map(EnchantUtils::getLocalized).filter(Objects::nonNull) + .forEach(conf -> conflicts.add(line.replace(GENERIC_NAME, conf))); continue; } conflicts.add(line); @@ -208,17 +188,40 @@ public class EnchantmentsListMenu extends ConfigMenu implemen } List obtaining = new ArrayList<>(); - for (String line : this.enchantLoreObtaining) { - if (line.contains("%type%")) { - for (ObtainType obtainType : ObtainType.values()) { - if (!enchant.isObtainable(obtainType)) continue; - obtaining.add(line.replace("%type%", this.plugin.getLangManager().getEnum(obtainType))); + if (Config.isCustomDistribution()) { + for (String line : this.enchantLoreObtaining) { + if (line.contains(GENERIC_TYPE)) { + for (DistributionWay distributionWay : DistributionWay.values()) { + if (enchant.getDistributionOptions() instanceof CustomDistribution distribution) { + if (!distribution.isDistributable(distributionWay)) continue; + } + + obtaining.add(line.replace(GENERIC_TYPE, this.plugin.getLangManager().getEnum(distributionWay))); + } + continue; } - continue; + obtaining.add(line); } - obtaining.add(line); } - ItemReplacer.create(icon).hideFlags().trimmed().setDisplayName(this.enchantName).setLore(this.enchantLoreMain).replaceLoreExact(PLACEHOLDER_CHARGES, enchant.isChargesEnabled() ? new ArrayList<>(this.enchantLoreCharges) : Collections.emptyList()).replaceLoreExact(PLACEHOLDER_CONFLICTS, conflicts).replaceLoreExact(PLACEHOLDER_OBTAINING, obtaining).replaceLoreExact("%enchantment_description%", enchant.formatDescription()).replace(new PlaceholderMap[]{enchant.getPlaceholders(level)}).replace(Colorizer::apply).writeMeta(); + + List charges = new ArrayList<>(); + if (enchant.isChargesEnabled()) { + for (String line : this.enchantLoreCharges) { + charges.add(line + .replace(GENERIC_AMOUNT, NumberUtil.format(enchant.getChargesMax(level))) + .replace(GENERIC_ITEM, ItemUtil.getItemName(enchant.getChargesFuel())) + ); + } + } + + ItemReplacer.create(icon).hideFlags().trimmed() + .setDisplayName(this.enchantName) + .setLore(this.enchantLoreMain) + .replaceLoreExact(PLACEHOLDER_CHARGES, charges) + .replaceLoreExact(PLACEHOLDER_CONFLICTS, conflicts) + .replaceLoreExact(PLACEHOLDER_OBTAINING, obtaining) + .replace(enchant.getPlaceholders(level)) + .writeMeta(); return icon; } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/EnchantRegistry.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/EnchantRegistry.java index c4dc05c..3be9c34 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/EnchantRegistry.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/EnchantRegistry.java @@ -10,13 +10,11 @@ import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.Version; -import su.nexmedia.engine.api.manager.AbstractManager; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.Rarity; import su.nightexpress.excellentenchants.api.enchantment.type.*; import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; import su.nightexpress.excellentenchants.enchantment.impl.armor.*; import su.nightexpress.excellentenchants.enchantment.impl.bow.*; import su.nightexpress.excellentenchants.enchantment.impl.fishing.*; @@ -28,21 +26,26 @@ import su.nightexpress.excellentenchants.enchantment.impl.weapon.*; import su.nightexpress.excellentenchants.enchantment.registry.wrapper.DataGather; import su.nightexpress.excellentenchants.enchantment.registry.wrapper.DataGathers; import su.nightexpress.excellentenchants.enchantment.registry.wrapper.WrappedEvent; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; -import su.nightexpress.excellentenchants.tier.Tier; +import su.nightexpress.nightcore.manager.SimpleManager; +import su.nightexpress.nightcore.util.BukkitThing; +import su.nightexpress.nightcore.util.FileUtil; +import su.nightexpress.nightcore.util.Version; +import java.io.File; import java.util.*; -import java.util.function.Supplier; +import java.util.function.Function; import java.util.stream.Collectors; -public class EnchantRegistry extends AbstractManager { +public class EnchantRegistry extends SimpleManager { - public static final Map REGISTRY_MAP = new HashMap<>(); - private static final Map, Set> ENCHANTS_MAP = new HashMap<>(); + public static final Map BY_KEY = new HashMap<>(); + public static final Map BY_ID = new HashMap<>(); + + private static final Map, Set> ENCHANTS_MAP = new HashMap<>(); private boolean isLocked; - public EnchantRegistry(@NotNull ExcellentEnchants plugin) { + public EnchantRegistry(@NotNull ExcellentEnchantsPlugin plugin) { super(plugin); } @@ -66,118 +69,105 @@ public class EnchantRegistry extends AbstractManager { // Prevent to register enchantments during the runtime. if (this.isLocked) { - REGISTRY_MAP.values().forEach(enchant -> { - enchant.loadSettings(); - enchant.registerListeners(); - }); + BY_ID.values().forEach(this::load); return; } - //if (Version.isAtLeast(Version.V1_20_R3)) { - this.plugin.getEnchantNMS().unfreezeRegistry(); - //} - //else { - // Reflex.setFieldValue(Enchantment.class, "acceptingNew", true); - //} + this.plugin.getEnchantNMS().unfreezeRegistry(); // Fishing Enchants - this.register(AutoReelEnchant.ID,() -> new AutoReelEnchant(plugin)); - this.register(DoubleCatchEnchant.ID, () -> new DoubleCatchEnchant(plugin)); - this.register(SeasonedAnglerEnchant.ID, () -> new SeasonedAnglerEnchant(plugin)); - this.register(SurvivalistEnchant.ID, () -> new SurvivalistEnchant(plugin)); - this.register(CurseOfDrownedEnchant.ID, () -> new CurseOfDrownedEnchant(plugin)); - this.register(RiverMasterEnchant.ID, () -> new RiverMasterEnchant(plugin)); + this.register(AutoReelEnchant.ID, file -> new AutoReelEnchant(plugin, file)); + this.register(DoubleCatchEnchant.ID, file -> new DoubleCatchEnchant(plugin, file)); + this.register(SeasonedAnglerEnchant.ID, file -> new SeasonedAnglerEnchant(plugin, file)); + this.register(SurvivalistEnchant.ID, file -> new SurvivalistEnchant(plugin, file)); + this.register(CurseOfDrownedEnchant.ID, file -> new CurseOfDrownedEnchant(plugin, file)); + this.register(RiverMasterEnchant.ID, file -> new RiverMasterEnchant(plugin, file)); // Tool enchants - this.register(BlastMiningEnchant.ID, () -> new BlastMiningEnchant(plugin)); - this.register(CurseOfBreakingEnchant.ID, () -> new CurseOfBreakingEnchant(plugin)); - this.register(CurseOfMisfortuneEnchant.ID, () -> new CurseOfMisfortuneEnchant(plugin)); - this.register(DivineTouchEnchant.ID, () -> new DivineTouchEnchant(plugin)); - this.register(HasteEnchant.ID, () -> new HasteEnchant(plugin)); - this.register(LuckyMinerEnchant.ID, () -> new LuckyMinerEnchant(plugin)); - this.register(ReplanterEnchant.ID, () -> new ReplanterEnchant(plugin)); - this.register(SilkChestEnchant.ID, () -> new SilkChestEnchant(plugin)); - this.register(SmelterEnchant.ID, () -> new SmelterEnchant(plugin)); - this.register(TelekinesisEnchant.ID, () -> new TelekinesisEnchant(plugin)); - this.register(TreasuresEnchant.ID, () -> new TreasuresEnchant(plugin)); - this.register(TunnelEnchant.ID, () -> new TunnelEnchant(plugin)); - this.register(VeinminerEnchant.ID, () -> new VeinminerEnchant(plugin)); + this.register(BlastMiningEnchant.ID, file -> new BlastMiningEnchant(plugin, file)); + this.register(CurseOfBreakingEnchant.ID, file -> new CurseOfBreakingEnchant(plugin, file)); + this.register(CurseOfMisfortuneEnchant.ID, file -> new CurseOfMisfortuneEnchant(plugin, file)); + this.register(SilkSpawnerEnchant.ID, file -> new SilkSpawnerEnchant(plugin, file)); + this.register(HasteEnchant.ID, file -> new HasteEnchant(plugin, file)); + this.register(LuckyMinerEnchant.ID, file -> new LuckyMinerEnchant(plugin, file)); + this.register(ReplanterEnchant.ID, file -> new ReplanterEnchant(plugin, file)); + this.register(SilkChestEnchant.ID, file -> new SilkChestEnchant(plugin, file)); + this.register(SmelterEnchant.ID, file -> new SmelterEnchant(plugin, file)); + this.register(TelekinesisEnchant.ID, file -> new TelekinesisEnchant(plugin, file)); + this.register(TreasureHunterEnchant.ID, file -> new TreasureHunterEnchant(plugin, file)); + this.register(TunnelEnchant.ID, file -> new TunnelEnchant(plugin, file)); + this.register(VeinminerEnchant.ID, file -> new VeinminerEnchant(plugin, file)); // Weapon enchants - this.register(EnchantBaneOfNetherspawn.ID, () -> new EnchantBaneOfNetherspawn(plugin)); - this.register(EnchantBlindness.ID, () -> new EnchantBlindness(plugin)); - this.register(EnchantConfusion.ID, () -> new EnchantConfusion(plugin)); - this.register(EnchantCutter.ID, () -> new EnchantCutter(plugin)); - this.register(CurseOfDeathEnchant.ID, () -> new CurseOfDeathEnchant(plugin)); - this.register(EnchantDecapitator.ID, () -> new EnchantDecapitator(plugin)); - this.register(EnchantDoubleStrike.ID, () -> new EnchantDoubleStrike(plugin)); - this.register(EnchantExhaust.ID, () -> new EnchantExhaust(plugin)); - this.register(EnchantExpHunter.ID, () -> new EnchantExpHunter(plugin)); - this.register(EnchantIceAspect.ID, () -> new EnchantIceAspect(plugin)); - this.register(EnchantInfernus.ID, () -> new EnchantInfernus(plugin)); - this.register(EnchantNimble.ID, () -> new EnchantNimble(plugin)); - this.register(EnchantParalyze.ID, () -> new EnchantParalyze(plugin)); - this.register(EnchantCure.ID, () -> new EnchantCure(plugin)); - this.register(EnchantRage.ID, () -> new EnchantRage(plugin)); - this.register(EnchantRocket.ID, () -> new EnchantRocket(plugin)); - this.register(EnchantScavenger.ID, () -> new EnchantScavenger(plugin)); - this.register(EnchantSurprise.ID, () -> new EnchantSurprise(plugin)); - this.register(SwiperEnchant.ID, () -> new SwiperEnchant(plugin)); - this.register(EnchantTemper.ID, () -> new EnchantTemper(plugin)); - this.register(EnchantThrifty.ID, () -> new EnchantThrifty(plugin)); - this.register(EnchantThunder.ID, () -> new EnchantThunder(plugin)); - this.register(EnchantVampire.ID, () -> new EnchantVampire(plugin)); - this.register(EnchantVenom.ID, () -> new EnchantVenom(plugin)); - this.register(EnchantVillageDefender.ID, () -> new EnchantVillageDefender(plugin)); - this.register(EnchantWither.ID, () -> new EnchantWither(plugin)); + this.register(BaneOfNetherspawnEnchant.ID, file -> new BaneOfNetherspawnEnchant(plugin, file)); + this.register(BlindnessEnchant.ID, file -> new BlindnessEnchant(plugin, file)); + this.register(ConfusionEnchant.ID, file -> new ConfusionEnchant(plugin, file)); + this.register(CutterEnchant.ID, file -> new CutterEnchant(plugin, file)); + this.register(CurseOfDeathEnchant.ID, file -> new CurseOfDeathEnchant(plugin, file)); + this.register(EnchantDecapitator.ID, file -> new EnchantDecapitator(plugin, file)); + this.register(DoubleStrikeEnchant.ID, file -> new DoubleStrikeEnchant(plugin, file)); + this.register(ExhaustEnchant.ID, file -> new ExhaustEnchant(plugin, file)); + this.register(WisdomEnchant.ID, file -> new WisdomEnchant(plugin, file)); + this.register(IceAspectEnchant.ID, file -> new IceAspectEnchant(plugin, file)); + this.register(InfernusEnchant.ID, file -> new InfernusEnchant(plugin, file)); + this.register(NimbleEnchant.ID, file -> new NimbleEnchant(plugin, file)); + this.register(ParalyzeEnchant.ID, file -> new ParalyzeEnchant(plugin, file)); + this.register(CureEnchant.ID, file -> new CureEnchant(plugin, file)); + this.register(RageEnchant.ID, file -> new RageEnchant(plugin, file)); + this.register(RocketEnchant.ID, file -> new RocketEnchant(plugin, file)); + this.register(ScavengerEnchant.ID, file -> new ScavengerEnchant(plugin, file)); + this.register(SurpriseEnchant.ID, file -> new SurpriseEnchant(plugin, file)); + this.register(SwiperEnchant.ID, file -> new SwiperEnchant(plugin, file)); + this.register(TemperEnchant.ID, file -> new TemperEnchant(plugin, file)); + this.register(ThriftyEnchant.ID, file -> new ThriftyEnchant(plugin, file)); + this.register(ThunderEnchant.ID, file -> new ThunderEnchant(plugin, file)); + this.register(VampireEnchant.ID, file -> new VampireEnchant(plugin, file)); + this.register(VenomEnchant.ID, file -> new VenomEnchant(plugin, file)); + this.register(VillageDefenderEnchant.ID, file -> new VillageDefenderEnchant(plugin, file)); + this.register(WitherEnchant.ID, file -> new WitherEnchant(plugin, file)); // Armor enchants - this.register(AquamanEnchant.ID, () -> new AquamanEnchant(plugin)); - this.register(JumpingEnchant.ID, () -> new JumpingEnchant(plugin)); - this.register(ColdSteelEnchant.ID, () -> new ColdSteelEnchant(plugin)); - this.register(IceShieldEnchant.ID, () -> new IceShieldEnchant(plugin)); - this.register(ElementalProtectionEnchant.ID, () -> new ElementalProtectionEnchant(plugin)); - this.register(FireShieldEnchant.ID, () -> new FireShieldEnchant(plugin)); - this.register(FlameWalkerEnchant.ID, () -> new FlameWalkerEnchant(plugin)); - this.register(HardenedEnchant.ID, () -> new HardenedEnchant(plugin)); - this.register(NightVisionEnchant.ID, () -> new NightVisionEnchant(plugin)); - this.register(RegrowthEnchant.ID, () -> new RegrowthEnchant(plugin)); - this.register(SaturationEnchant.ID, () -> new SaturationEnchant(plugin)); - this.register(KamikadzeEnchant.ID, () -> new KamikadzeEnchant(plugin)); - this.register(StoppingForceEnchant.ID, () -> new StoppingForceEnchant(plugin)); - this.register(SpeedyEnchant.ID, () -> new SpeedyEnchant(plugin)); + this.register(WaterBreathingEnchant.ID, file -> new WaterBreathingEnchant(plugin, file)); + this.register(JumpingEnchant.ID, file -> new JumpingEnchant(plugin, file)); + this.register(ColdSteelEnchant.ID, file -> new ColdSteelEnchant(plugin, file)); + this.register(IceShieldEnchant.ID, file -> new IceShieldEnchant(plugin, file)); + this.register(ElementalProtectionEnchant.ID, file -> new ElementalProtectionEnchant(plugin, file)); + this.register(FireShieldEnchant.ID, file -> new FireShieldEnchant(plugin, file)); + this.register(FlameWalkerEnchant.ID, file -> new FlameWalkerEnchant(plugin, file)); + this.register(HardenedEnchant.ID, file -> new HardenedEnchant(plugin, file)); + this.register(NightVisionEnchant.ID, file -> new NightVisionEnchant(plugin, file)); + this.register(RegrowthEnchant.ID, file -> new RegrowthEnchant(plugin, file)); + this.register(SaturationEnchant.ID, file -> new SaturationEnchant(plugin, file)); + this.register(KamikadzeEnchant.ID, file -> new KamikadzeEnchant(plugin, file)); + this.register(StoppingForceEnchant.ID, file -> new StoppingForceEnchant(plugin, file)); + this.register(SpeedyEnchant.ID, file -> new SpeedyEnchant(plugin, file)); // Bow enchants - this.register(EnchantBomber.ID, () -> new EnchantBomber(plugin)); - this.register(EnchantConfusingArrows.ID, () -> new EnchantConfusingArrows(plugin)); - this.register(EnchantDragonfireArrows.ID, () -> new EnchantDragonfireArrows(plugin)); - this.register(EnchantElectrifiedArrows.ID, () -> new EnchantElectrifiedArrows(plugin)); - this.register(EnchantEnderBow.ID, () -> new EnchantEnderBow(plugin)); - this.register(EnchantExplosiveArrows.ID, () -> new EnchantExplosiveArrows(plugin)); - this.register(FlareEnchant.ID, () -> new FlareEnchant(plugin)); - this.register(EnchantGhast.ID, () -> new EnchantGhast(plugin)); - this.register(EnchantHover.ID, () -> new EnchantHover(plugin)); - this.register(SniperEnchant.ID, () -> new SniperEnchant(plugin)); - this.register(EnchantPoisonedArrows.ID, () -> new EnchantPoisonedArrows(plugin)); - this.register(VampiricArrowsEnchant.ID, () -> new VampiricArrowsEnchant(plugin)); - this.register(EnchantWitheredArrows.ID, () -> new EnchantWitheredArrows(plugin)); + this.register(BomberEnchant.ID, file -> new BomberEnchant(plugin, file)); + this.register(ConfusingArrowsEnchant.ID, file -> new ConfusingArrowsEnchant(plugin, file)); + this.register(DragonfireArrowsEnchant.ID, file -> new DragonfireArrowsEnchant(plugin, file)); + this.register(ElectrifiedArrowsEnchant.ID, file -> new ElectrifiedArrowsEnchant(plugin, file)); + this.register(EnderBowEnchant.ID, file -> new EnderBowEnchant(plugin, file)); + this.register(ExplosiveArrowsEnchant.ID, file -> new ExplosiveArrowsEnchant(plugin, file)); + this.register(FlareEnchant.ID, file -> new FlareEnchant(plugin, file)); + this.register(GhastEnchant.ID, file -> new GhastEnchant(plugin, file)); + this.register(HoverEnchant.ID, file -> new HoverEnchant(plugin, file)); + this.register(SniperEnchant.ID, file -> new SniperEnchant(plugin, file)); + this.register(PoisonedArrowsEnchant.ID, file -> new PoisonedArrowsEnchant(plugin, file)); + this.register(VampiricArrowsEnchant.ID, file -> new VampiricArrowsEnchant(plugin, file)); + this.register(WitheredArrowsEnchant.ID, file -> new WitheredArrowsEnchant(plugin, file)); if (Version.isAbove(Version.V1_18_R2)) { - this.register(DarknessArrowsEnchant.ID, () -> new DarknessArrowsEnchant(plugin)); - this.register(DarknessCloakEnchant.ID, () -> new DarknessCloakEnchant(plugin)); + this.register(DarknessArrowsEnchant.ID, file -> new DarknessArrowsEnchant(plugin, file)); + this.register(DarknessCloakEnchant.ID, file -> new DarknessCloakEnchant(plugin, file)); } // Universal - this.register(CurseOfFragilityEnchant.ID, () -> new CurseOfFragilityEnchant(plugin)); - this.register(CurseOfMediocrityEnchant.ID, () -> new CurseOfMediocrityEnchant(plugin)); - this.register(SoulboundEnchant.ID, () -> new SoulboundEnchant(plugin)); - this.register(RestoreEnchant.ID, () -> new RestoreEnchant(plugin)); + this.register(CurseOfFragilityEnchant.ID, file -> new CurseOfFragilityEnchant(plugin, file)); + this.register(CurseOfMediocrityEnchant.ID, file -> new CurseOfMediocrityEnchant(plugin, file)); + this.register(SoulboundEnchant.ID, file -> new SoulboundEnchant(plugin, file)); + this.register(RestoreEnchant.ID, file -> new RestoreEnchant(plugin, file)); - //if (Version.isAtLeast(Version.V1_20_R3)) { - this.plugin.getEnchantNMS().freezeRegistry(); - //} - //else { - // Enchantment.stopAcceptingRegistrations(); - //} + this.plugin.getEnchantNMS().freezeRegistry(); this.plugin.info("Enchantments Registered: " + EnchantRegistry.getRegistered().size()); this.isLocked = true; } @@ -189,11 +179,11 @@ public class EnchantRegistry extends AbstractManager { } } - public void registerType(@NotNull Class enchantClass) { + public void registerType(@NotNull Class enchantClass) { ENCHANTS_MAP.computeIfAbsent(enchantClass, k -> new HashSet<>()); } - public void registerWrapper(@NotNull Class eventClass, + public void registerWrapper(@NotNull Class eventClass, @NotNull Class enchantClass, @NotNull DataGather dataGather) { @@ -205,8 +195,8 @@ public class EnchantRegistry extends AbstractManager { this.registerType(enchantClass); } - private boolean registerEnchantType(@NotNull T enchant) { - Class enchantClass = enchant.getClass(); + private boolean registerEnchantType(@NotNull T enchant) { + Class enchantClass = enchant.getClass(); Set> assignables = ENCHANTS_MAP.keySet().stream().filter(clazz -> clazz.isAssignableFrom(enchantClass)).collect(Collectors.toSet()); if (assignables.isEmpty()) { @@ -218,32 +208,34 @@ public class EnchantRegistry extends AbstractManager { return true; } - private void register(@NotNull String id, @NotNull Supplier supplier) { - if (Config.ENCHANTMENTS_DISABLED.get().contains(id)) return; + private void register(@NotNull String id, @NotNull Function supplier) { + if (Config.ENCHANTMENTS_DISABLED_LIST.get().contains(id)) return; + File file = new File(plugin.getDataFolder() + Config.DIR_ENCHANTS, id + ".yml"); + FileUtil.create(file); - ExcellentEnchant enchant = supplier.get(); - if (EnchantUtils.getEnchantment(enchant.getKey()) /*Enchantment.getByKey(enchant.getKey())*/ != null) { - this.plugin.error("Could not register '" + enchant.getId() + "': Such enchantment already registered."); + EnchantmentData enchantmentData = supplier.apply(file); + if (BukkitThing.getEnchantment(enchantmentData.getId()) != null) { + this.plugin.error("Could not register '" + enchantmentData.getId() + "': Such enchantment already registered."); return; } - if (!this.registerEnchantType(enchant)) { + if (!this.registerEnchantType(enchantmentData) || !enchantmentData.checkServerRequirements()) { return; } - //if (Version.isAtLeast(Version.V1_20_R3)) { - this.plugin.getEnchantNMS().registerEnchantment(enchant); - //} - //else { - //Enchantment.registerEnchantment(enchant); - //} + this.load(enchantmentData); - REGISTRY_MAP.put(enchant.getKey(), enchant); - enchant.loadSettings(); - enchant.getConfig().saveChanges(); - enchant.registerListeners(); - this.plugin.info("Registered enchantment: " + enchant.getId()); + this.plugin.getEnchantNMS().registerEnchantment(enchantmentData); + + BY_KEY.put(NamespacedKey.minecraft(enchantmentData.getId()), enchantmentData); + BY_ID.put(enchantmentData.getId(), enchantmentData); + + this.plugin.info("Registered enchantment: " + enchantmentData.getId()); + } + + private void load(@NotNull EnchantmentData enchant) { + enchant.load(); } @NotNull @@ -252,34 +244,43 @@ public class EnchantRegistry extends AbstractManager { } @NotNull - public static Set getEnchantments(@NotNull Class clazz) { + public static Set getEnchantments(@NotNull Class clazz) { Set enchants = new HashSet<>(); ENCHANTS_MAP.getOrDefault(clazz, Collections.emptySet()).forEach(talent -> { enchants.add(clazz.cast(talent)); }); return enchants; - //Set set = new HashSet<>(ENCHANTS_MAP.getOrDefault(clazz, Collections.emptySet())); - //return (Set) set; - } - - @Nullable - public static ExcellentEnchant getById(@NotNull String id) { - return getByKey(EnchantUtils.createKey(id)); - } - - @Nullable - public static ExcellentEnchant getByKey(@NotNull NamespacedKey key) { - return REGISTRY_MAP.get(key); } @NotNull - public static Collection getRegistered() { - return REGISTRY_MAP.values(); + public static Set getEnchantments(@NotNull Rarity rarity) { + return BY_ID.values().stream() + .filter(enchantmentData -> enchantmentData.getRarity() == rarity) + .collect(Collectors.toCollection(HashSet::new)); + } + + public static boolean isRegistered(@NotNull String id) { + return getById(id) != null; + } + + @Nullable + public static EnchantmentData getById(@NotNull String id) { + return BY_ID.get(id.toLowerCase()); + } + + @Nullable + public static EnchantmentData getByKey(@NotNull NamespacedKey key) { + return BY_KEY.get(key); } @NotNull - public static Set getOfTier(@NotNull Tier tier) { - return getRegistered().stream().filter(enchant -> enchant.getTier() == tier).collect(Collectors.toCollection(HashSet::new)); + public static Set getByRarity(@NotNull Rarity rarity) { + return getRegistered().stream().filter(data -> data.getRarity() == rarity).collect(Collectors.toSet()); + } + + @NotNull + public static Collection getRegistered() { + return BY_ID.values(); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGather.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGather.java index 92c9679..bd775d2 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGather.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGather.java @@ -7,12 +7,12 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; import java.util.Map; -public abstract class DataGather { +public abstract class DataGather { @Nullable public abstract LivingEntity getEntity(@NotNull E event); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGathers.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGathers.java index 55658c9..b73b27f 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGathers.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/DataGathers.java @@ -14,10 +14,11 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.Version; -import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed; +import su.nightexpress.excellentenchants.api.enchantment.data.ArrowData; import su.nightexpress.excellentenchants.api.enchantment.type.*; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; +import su.nightexpress.excellentenchants.enchantment.util.EnchantedProjectile; +import su.nightexpress.nightcore.util.Version; import java.util.Collections; import java.util.HashMap; @@ -96,14 +97,19 @@ public class DataGathers { @Override public boolean useEnchant(@NotNull EntityShootBowEvent event, @NotNull LivingEntity entity, @NotNull ItemStack item, @NotNull BowEnchant enchant, int level) { - if (enchant.onShoot(event, entity, item, level)) { - if (enchant instanceof Arrowed arrowed && event.getProjectile() instanceof Projectile projectile) { - arrowed.addData(projectile); - arrowed.addTrail(projectile); + boolean onShoot = enchant.onShoot(event, entity, item, level); + + if (event.getProjectile() instanceof Projectile projectile) { + EnchantedProjectile enchantedProjectile = EnchantUtils.getEnchantedProjectile(projectile); + if (enchantedProjectile != null && onShoot) { + enchantedProjectile.getEnchantments().put(enchant, level); + if (enchant.hasVisualEffects() && enchant instanceof ArrowData arrowData && !arrowData.getProjectileTrail().isEmpty()) { + enchantedProjectile.getParticles().add(arrowData.getProjectileTrail()); + } } - return true; } - return false; + + return onShoot; } }; @@ -129,10 +135,13 @@ public class DataGathers { @NotNull @Override public Map> getEnchants(@NotNull ProjectileHitEvent event, @NotNull Class enchantClass, @NotNull LivingEntity entity) { + EnchantedProjectile enchantedProjectile = EnchantUtils.getEnchantedProjectile(event.getEntity()); + if (enchantedProjectile == null) return Collections.emptyMap(); + Map> map = new HashMap<>(); - ItemStack bow = EnchantUtils.getSourceWeapon(event.getEntity()); + ItemStack bow = enchantedProjectile.getItem(); if (bow != null) { - map.put(bow, EnchantUtils.getExcellents(bow, enchantClass)); + map.put(bow, enchantedProjectile.getEnchantments()); } return map; } @@ -170,10 +179,13 @@ public class DataGathers { public Map> getEnchants(@NotNull EntityDamageByEntityEvent event, @NotNull Class enchantClass, @NotNull LivingEntity entity) { if (!(event.getDamager() instanceof Projectile projectile)) return Collections.emptyMap(); + EnchantedProjectile enchantedProjectile = EnchantUtils.getEnchantedProjectile(projectile); + if (enchantedProjectile == null) return Collections.emptyMap(); + Map> map = new HashMap<>(); - ItemStack bow = EnchantUtils.getSourceWeapon(projectile); + ItemStack bow = enchantedProjectile.getItem(); if (bow != null) { - map.put(bow, EnchantUtils.getExcellents(bow, enchantClass)); + map.put(bow, enchantedProjectile.getEnchantments()); } return map; } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/WrappedEvent.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/WrappedEvent.java index c210447..ededc3e 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/WrappedEvent.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/registry/wrapper/WrappedEvent.java @@ -7,12 +7,13 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.plugin.EventExecutor; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; -import su.nightexpress.excellentenchants.config.Config; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; -public class WrappedEvent implements Listener, EventExecutor { +import java.util.concurrent.atomic.AtomicBoolean; + +public class WrappedEvent implements Listener, EventExecutor { //private final ExcellentEnchants plugin; private final EventPriority priority; @@ -20,7 +21,7 @@ public class WrappedEvent implements Li private final Class enchantClass; private final DataGather dataGather; - public WrappedEvent(@NotNull ExcellentEnchants plugin, + public WrappedEvent(@NotNull ExcellentEnchantsPlugin plugin, @NotNull EventPriority priority, @NotNull Class eventClass, @NotNull Class enchantClass, @@ -40,18 +41,22 @@ public class WrappedEvent implements Li LivingEntity entity = this.dataGather.getEntity(event); if (entity == null) return; - Player player = entity instanceof Player p1 ? p1 : null; + Player player = entity instanceof Player user ? user : null; + AtomicBoolean needUpdate = new AtomicBoolean(false); this.dataGather.getEnchants(event, this.enchantClass, entity).forEach((item, enchants) -> { - enchants.forEach(((enchant, level) -> { + enchants.forEach((enchant, level) -> { + if (enchant.isChargesEnabled() && this.priority == EventPriority.MONITOR) needUpdate.set(true); + if (!this.dataGather.checkPriority(enchant, this.priority)) return; if (!enchant.isAvailableToUse(entity)) return; if (enchant.isOutOfCharges(item)) return; if (this.dataGather.useEnchant(event, entity, item, enchant, level)) { enchant.consumeChargesNoUpdate(item, level); } - })); - if (this.priority == EventPriority.MONITOR && Config.ENCHANTMENTS_CHARGES_ENABLED.get() && player != null) { + }); + + if (needUpdate.get() && player != null) { EnchantUtils.updateDisplay(item); } }); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/task/ArrowTrailsTask.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/task/ArrowTrailsTask.java deleted file mode 100644 index e5b8705..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/task/ArrowTrailsTask.java +++ /dev/null @@ -1,38 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.task; - -import org.bukkit.entity.Projectile; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.server.AbstractTask; -import su.nexmedia.engine.utils.values.UniParticle; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.config.Config; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class ArrowTrailsTask extends AbstractTask { - - private static final Map> TRAILS_MAP = new ConcurrentHashMap<>(); - - public ArrowTrailsTask(@NotNull ExcellentEnchants plugin) { - super(plugin, Config.TASKS_ARROW_TRAIL_TICKS_INTERVAL.get(), true); - TRAILS_MAP.clear(); - } - - @Override - public void action() { - TRAILS_MAP.keySet().removeIf(projectile -> !projectile.isValid() || projectile.isDead()); - - TRAILS_MAP.forEach((arrow, effects) -> { - effects.forEach(entry -> { - entry.play(arrow.getLocation(), 0f, 0f, 10); - }); - }); - } - - public static void add(@NotNull Projectile projectile, @NotNull UniParticle particle) { - TRAILS_MAP.computeIfAbsent(projectile, list -> new HashSet<>()).add(particle); - } -} \ No newline at end of file diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/task/PassiveEnchantsTask.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/task/PassiveEnchantsTask.java deleted file mode 100644 index 4ef6467..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/task/PassiveEnchantsTask.java +++ /dev/null @@ -1,71 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.task; - -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.server.AbstractTask; -import su.nexmedia.engine.utils.Pair; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant; -import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; -import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; -import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -public class PassiveEnchantsTask extends AbstractTask { - - private final Set> enchants; - - public PassiveEnchantsTask(@NotNull ExcellentEnchants plugin) { - super(plugin, Config.TASKS_PASSIVE_ENCHANTS_TRIGGER_INTERVAL.get(), false); - this.enchants = new HashSet<>(); - - EnchantRegistry.getEnchantments(PassiveEnchant.class).forEach(enchant -> { - ExcellentEnchant excellent = EnchantRegistry.getByKey(enchant.getKey()); - if (excellent == null) return; - - this.enchants.add(Pair.of(enchant, excellent)); - }); - } - - @Override - public void action() { - if (this.enchants.isEmpty()) return; - - var entities = this.getEntities(); - - this.enchants.forEach(pair -> { - PassiveEnchant enchant = pair.getFirst(); - ExcellentEnchant excellent = pair.getSecond(); - if (!enchant.isTriggerTime()) return; - - for (LivingEntity entity : entities) { - EnchantUtils.getEquipped(entity, excellent).forEach((item, level) -> { - if (!enchant.isAvailableToUse(entity)) return; - if (enchant.isOutOfCharges(item)) return; - if (enchant.onTrigger(entity, item, level)) { - enchant.consumeCharges(item, level); - } - }); - } - - enchant.updateTriggerTime(); - }); - } - - @NotNull - private Collection getEntities() { - Set list = new HashSet<>(plugin.getServer().getOnlinePlayers()); - - if (Config.ENCHANTMENTS_ENTITY_PASSIVE_FOR_MOBS.get()) { - plugin.getServer().getWorlds().stream().filter(world -> !world.getPlayers().isEmpty()).forEach(world -> { - list.addAll(world.getEntitiesByClass(LivingEntity.class)); - }); - } - list.removeIf(entity -> entity.isDead() || !entity.isValid()); - return list; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/type/FitItemType.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/type/FitItemType.java deleted file mode 100644 index 392e94c..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/type/FitItemType.java +++ /dev/null @@ -1,59 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.type; - -import org.bukkit.Material; -import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.ItemUtil; -import su.nightexpress.excellentenchants.config.Config; - -public enum FitItemType { - - HELMET, CHESTPLATE, LEGGINGS, BOOTS, ELYTRA, - WEAPON, TOOL, ARMOR, UNIVERSAL, - SWORD, TRIDENT, AXE, BOW, CROSSBOW, - HOE, PICKAXE, SHOVEL, FISHING_ROD; - - @Nullable - public static FitItemType getByEnchantmentTarget(@NotNull EnchantmentTarget target) { - return switch (target) { - case ARMOR -> ARMOR; - case ARMOR_FEET -> BOOTS; - case ARMOR_LEGS -> LEGGINGS; - case ARMOR_TORSO -> CHESTPLATE; - case ARMOR_HEAD -> HELMET; - case WEAPON -> WEAPON; - case TOOL -> TOOL; - case BOW -> BOW; - case FISHING_ROD -> FISHING_ROD; - case TRIDENT -> TRIDENT; - case CROSSBOW -> CROSSBOW; - case BREAKABLE, WEARABLE -> UNIVERSAL; - default -> null; - }; - } - - public boolean isIncluded(@NotNull ItemStack item) { - return switch (this) { - case UNIVERSAL -> ARMOR.isIncluded(item) || WEAPON.isIncluded(item) || TOOL.isIncluded(item) || BOW.isIncluded(item) || FISHING_ROD.isIncluded(item) || ELYTRA.isIncluded(item); - case HELMET -> ItemUtil.isHelmet(item); - case CHESTPLATE -> ItemUtil.isChestplate(item) || (Config.ENCHANTMENTS_ITEM_CHESTPLATE_ENCHANTS_TO_ELYTRA.get() && ELYTRA.isIncluded(item)); - case LEGGINGS -> ItemUtil.isLeggings(item); - case BOOTS -> ItemUtil.isBoots(item); - case ELYTRA -> item.getType() == Material.ELYTRA; - case WEAPON -> SWORD.isIncluded(item) || ItemUtil.isTrident(item); - case TOOL -> ItemUtil.isTool(item); - case ARMOR -> ItemUtil.isArmor(item); - case SWORD -> ItemUtil.isSword(item) || (Config.ENCHANTMENTS_ITEM_SWORD_ENCHANTS_TO_AXES.get() && AXE.isIncluded(item)); - case TRIDENT -> ItemUtil.isTrident(item); - case AXE -> ItemUtil.isAxe(item); - case BOW -> item.getType() == Material.BOW || (Config.ENCHANTMENTS_ITEM_BOW_ENCHANTS_TO_CROSSBOW.get() && CROSSBOW.isIncluded(item)); - case CROSSBOW -> item.getType() == Material.CROSSBOW; - case HOE -> ItemUtil.isHoe(item); - case PICKAXE -> ItemUtil.isPickaxe(item); - case SHOVEL -> ItemUtil.isShovel(item); - case FISHING_ROD -> item.getType() == Material.FISHING_ROD; - }; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/type/ObtainType.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/type/ObtainType.java deleted file mode 100644 index c4c2ace..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/type/ObtainType.java +++ /dev/null @@ -1,23 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.type; - -import org.jetbrains.annotations.NotNull; - -public enum ObtainType { - - ENCHANTING("Enchanting_Table"), - VILLAGER("Villagers"), - LOOT_GENERATION("Loot_Generation"), - FISHING("Fishing"), - MOB_SPAWNING("Mob_Spawning"); - - private final String pathName; - - ObtainType(@NotNull String pathName) { - this.pathName = pathName; - } - - @NotNull - public String getPathName() { - return pathName; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantPlaceholders.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantPlaceholders.java new file mode 100644 index 0000000..721e7cb --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantPlaceholders.java @@ -0,0 +1,78 @@ +package su.nightexpress.excellentenchants.enchantment.util; + +import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.util.Pair; +import su.nightexpress.nightcore.util.placeholder.PlaceholderMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +public class EnchantPlaceholders { + + private final List>> keys; + + public EnchantPlaceholders() { + this(new ArrayList<>()); + } + + public EnchantPlaceholders(@NotNull EnchantPlaceholders other) { + this(other.getKeys()); + } + + public EnchantPlaceholders(@NotNull List>> keys) { + this.keys = new ArrayList<>(keys); + } + + @NotNull + public static EnchantPlaceholders fusion(@NotNull EnchantPlaceholders... others) { + EnchantPlaceholders map = new EnchantPlaceholders(); + for (EnchantPlaceholders other : others) { + map.add(other); + } + return map; + } + + @NotNull + public List>> getKeys() { + return keys; + } + + @NotNull + public EnchantPlaceholders add(@NotNull EnchantPlaceholders other) { + this.getKeys().addAll(other.getKeys()); + return this; + } + + @NotNull + public EnchantPlaceholders add(@NotNull String key, @NotNull String replacer) { + this.add(key, level -> replacer); + return this; + } + + @NotNull + public EnchantPlaceholders add(@NotNull String key, @NotNull Supplier replacer) { + this.add(key, level -> replacer.get()); + return this; + } + + @NotNull + public EnchantPlaceholders add(@NotNull String key, @NotNull Function replacer) { + this.getKeys().add(Pair.of(key, replacer)); + return this; + } + + public void clear() { + this.getKeys().clear(); + } + + @NotNull + public PlaceholderMap toMap(int level) { + List>> list = new ArrayList<>(); + this.getKeys().forEach(pair -> { + list.add(Pair.of(pair.getFirst(), () -> pair.getSecond().apply(level))); + }); + return new PlaceholderMap(list); + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantUtils.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantUtils.java index 9f18b3e..593aaa4 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantUtils.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantUtils.java @@ -1,50 +1,39 @@ package su.nightexpress.excellentenchants.enchantment.util; import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Registry; import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.EnchantmentTarget; -import org.bukkit.entity.Item; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; -import org.bukkit.event.block.BlockDropItemEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.Version; -import su.nexmedia.engine.lang.LangManager; -import su.nexmedia.engine.utils.EntityUtil; -import su.nexmedia.engine.utils.ItemUtil; -import su.nexmedia.engine.utils.PDCUtil; -import su.nightexpress.excellentenchants.ExcellentEnchantsAPI; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.config.Keys; import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; +import su.nightexpress.nightcore.language.LangAssets; +import su.nightexpress.nightcore.util.*; +import su.nightexpress.nightcore.util.text.NightMessage; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; public class EnchantUtils { - public static final NamespacedKey KEY_LORE_SIZE = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "lore_size"); - private static final String META_PROJECTILE_WEAPON = "sourceWeapon"; + private static final Map ENCHANTED_PROJECTILE_MAP = new ConcurrentHashMap<>(); private static boolean busyBreak = false; - public static void popResource(@NotNull BlockDropItemEvent event, @NotNull ItemStack itemStack) { - Item item = ExcellentEnchantsAPI.PLUGIN.getEnchantNMS().popResource(event.getBlock(), itemStack); - event.getItems().add(item); - } - public static boolean isBusyByOthers() { return false; } @@ -69,39 +58,24 @@ public class EnchantUtils { } } - @Nullable - public static Enchantment getEnchantment(@NotNull String id) { - return getEnchantment(createKey(id)); - } - - @Nullable - public static Enchantment getEnchantment(@NotNull NamespacedKey key) { - if (Version.isAtLeast(Version.V1_20_R3)) { - return Registry.ENCHANTMENT.get(key); - } - else { - return Enchantment.getByKey(key); - } - } - - @NotNull + /*@NotNull public static NamespacedKey createKey(@NotNull String id) { return NamespacedKey.minecraft(id.toLowerCase()); - } + }*/ @Nullable public static String getLocalized(@NotNull String keyRaw) { - Enchantment enchantment = getEnchantment(keyRaw); + Enchantment enchantment = BukkitThing.getEnchantment(keyRaw); return enchantment == null ? null : getLocalized(enchantment); } @NotNull public static String getLocalized(@NotNull Enchantment enchantment) { - ExcellentEnchant enchant = EnchantRegistry.getByKey(enchantment.getKey()); + EnchantmentData enchant = EnchantRegistry.getByKey(enchantment.getKey()); if (enchant != null) { - return enchant.getDisplayName(); + return enchant.getName(); } - return LangManager.getEnchantment(enchantment); + return LangAssets.get(enchantment); } public static boolean isEnchantable(@NotNull ItemStack item) { @@ -110,14 +84,14 @@ public class EnchantUtils { return item.getType() == Material.ENCHANTED_BOOK || Stream.of(EnchantmentTarget.values()).anyMatch(target -> target.includes(item)); } - public static boolean isBook(@NotNull ItemStack item) { - return item.getType() == Material.BOOK || item.getType() == Material.ENCHANTED_BOOK; + public static boolean isEnchantedBook(@NotNull ItemStack item) { + return /*item.getType() == Material.BOOK || */item.getType() == Material.ENCHANTED_BOOK; } public static boolean add(@NotNull ItemStack item, @NotNull Enchantment enchantment, int level, boolean force) { - if (!force && (!enchantment.canEnchantItem(item) && !isBook(item))) return false; + if (!force && (!enchantment.canEnchantItem(item) && !isEnchantedBook(item))) return false; - remove(item, enchantment); + //remove(item, enchantment); ItemMeta meta = item.getItemMeta(); if (meta == null) return false; @@ -133,6 +107,15 @@ public class EnchantUtils { return true; } + public static void removeAll(@NotNull ItemStack item) { + if (Version.isAtLeast(Version.V1_20_R3)) { + item.removeEnchantments(); + } + else { + getEnchantments(item).keySet().forEach(item::removeEnchantment); + } + } + public static void remove(@NotNull ItemStack item, @NotNull Enchantment enchantment) { ItemMeta meta = item.getItemMeta(); if (meta instanceof EnchantmentStorageMeta storageMeta) { @@ -144,17 +127,17 @@ public class EnchantUtils { item.setItemMeta(meta); } - public static void updateChargesDisplay(@NotNull ItemStack item) { + /*public static void updateChargesDisplay(@NotNull ItemStack item) { if (Config.ENCHANTMENTS_CHARGES_ENABLED.get()) { updateDisplay(item); } - } + }*/ public static boolean canHaveDescription(@NotNull ItemStack item) { - if (!Config.ENCHANTMENTS_DESCRIPTION_ENABLED.get()) return false; + if (!Config.ENCHANTMENTS_DISPLAY_DESCRIPTION_ENABLED.get()) return false; - if (Config.ENCHANTMENTS_DESCRIPTION_BOOKS_ONLY.get()) { - return item.getType() == Material.ENCHANTED_BOOK; + if (Config.ENCHANTMENTS_DISPLAY_DESCRIPTION_BOOKS_ONLY.get()) { + return isEnchantedBook(item); } return true; @@ -167,40 +150,48 @@ public class EnchantUtils { if (meta == null) return false; if (!isEnchantable(item)) { - PDCUtil.remove(item, KEY_LORE_SIZE); + PDCUtil.remove(item, Keys.loreSize); return false; } - Map enchants = getExcellents(item); + Map enchantDataMap = Lists.sort(getCustomEnchantments(item), + Comparator.comparing( + (Map.Entry entry) -> entry.getKey().getRarity().getWeight() + ) + .thenComparing(entry -> entry.getKey().getName()) + ); - int sizeCached = PDCUtil.getInt(item, KEY_LORE_SIZE).orElse(0); - int sizeReal = enchants.size(); + int sizeCached = PDCUtil.getInt(item, Keys.loreSize).orElse(0); + int sizeReal = enchantDataMap.size(); if (sizeCached == 0 && sizeReal == 0) return false; List lore = meta.getLore() == null ? new ArrayList<>() : meta.getLore(); for (int index = 0; index < sizeCached && !lore.isEmpty(); index++) { lore.remove(0); } - //lore.removeIf(str -> enchants.keySet().stream().anyMatch(enchant -> str.contains(enchant.getDisplayName()))); if (!meta.hasItemFlag(ItemFlag.HIDE_ENCHANTS)) { if (canHaveDescription(item)) { - enchants.forEach((enchant, level) -> { - lore.addAll(0, enchant.formatDescription(level)); - }); - sizeReal += enchants.keySet().stream().map(ExcellentEnchant::getDescription).mapToInt(List::size).sum(); + for (var entry : enchantDataMap.entrySet()) { + List description = entry.getKey().getDescriptionReplaced(entry.getValue()); + + lore.addAll(0, NightMessage.asLegacy(description)); + sizeReal += description.size(); + } } - enchants.forEach((enchant, level) -> { - lore.add(0, enchant.getNameFormatted(level, getCharges(meta, enchant))); + enchantDataMap.forEach((enchant, level) -> { + lore.add(0, NightMessage.asLegacy(enchant.getNameFormatted(level, enchant.getCharges(meta)))); }); } else sizeReal = 0; meta.setLore(lore); + if (sizeReal > 0) { - PDCUtil.set(meta, KEY_LORE_SIZE, sizeReal); + PDCUtil.set(meta, Keys.loreSize, sizeReal); } - else PDCUtil.remove(meta, KEY_LORE_SIZE); + else PDCUtil.remove(meta, Keys.loreSize); + item.setItemMeta(meta); return true; } @@ -217,25 +208,21 @@ public class EnchantUtils { } @NotNull - public static Map getAll(@NotNull ItemStack item) { + public static Map getEnchantments(@NotNull ItemStack item) { ItemMeta meta = item.getItemMeta(); - return meta == null ? Collections.emptyMap() : getAll(meta); + return meta == null ? Collections.emptyMap() : getEnchantments(meta); } @NotNull - public static Map getAll(@NotNull ItemMeta meta) { - return (meta instanceof EnchantmentStorageMeta meta2) ? meta2.getStoredEnchants() : meta.getEnchants(); - } - - public static int getAmount(@NotNull ItemStack item) { - return getAll(item).size(); + public static Map getEnchantments(@NotNull ItemMeta meta) { + return (meta instanceof EnchantmentStorageMeta storageMeta) ? storageMeta.getStoredEnchants() : meta.getEnchants(); } public static boolean contains(@NotNull ItemStack item, @NotNull String id) { - ExcellentEnchant enchant = EnchantRegistry.getById(id); + EnchantmentData enchant = EnchantRegistry.getById(id); if (enchant == null) return false; - return contains(item, enchant.getBackend()); + return contains(item, enchant.getEnchantment()); } public static boolean contains(@NotNull ItemStack item, @NotNull Enchantment enchantment) { @@ -243,86 +230,32 @@ public class EnchantUtils { } public static int getLevel(@NotNull ItemStack item, @NotNull Enchantment enchant) { - return getAll(item).getOrDefault(enchant, 0); + return getEnchantments(item).getOrDefault(enchant, 0); } - public static int getCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) { - return enchant.isChargesEnabled() ? PDCUtil.getInt(item, enchant.getChargesKey()).orElse(0) : -1; + public static int countEnchantments(@NotNull ItemStack item) { + return getEnchantments(item).size(); } - public static int getCharges(@NotNull ItemMeta meta, @NotNull ExcellentEnchant enchant) { - return enchant.isChargesEnabled() ? PDCUtil.getInt(meta, enchant.getChargesKey()).orElse(0) : -1; - } - - public static boolean isOutOfCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) { - return enchant.isChargesEnabled() && getCharges(item, enchant) == 0; - } - - public static boolean isFullOfCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) { - if (!enchant.isChargesEnabled()) return true; - - int level = getLevel(item, enchant.getBackend()); - int max = enchant.getChargesMax(level); - return getCharges(item, enchant) == max; - } - - public static void consumeCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level) { - int has = getCharges(item, enchant); - int use = enchant.getChargesConsumeAmount(level); - setCharges(item, enchant, level, has < use ? 0 : has - use); - } - - /*public static void restoreCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) { - int level = getLevel(item, enchant); - restoreCharges(item, enchant, level); - }*/ - - public static void restoreCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level) { - setCharges(item, enchant, level, Integer.MAX_VALUE); - } - - public static void rechargeCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level) { - //if (!enchant.isChargesEnabled()) return; - - //int level = getLevel(item, enchant); - int recharge = enchant.getChargesRechargeAmount(level); - int has = getCharges(item, enchant); - int set = has + recharge; - setCharges(item, enchant, level, set); - } - - /*public static void setCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int charges) { - int level = getLevel(item, enchant); - setCharges(item, enchant, level, charges); - }*/ - - public static void setCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int level, int charges) { - if (!enchant.isChargesEnabled()) return; - - int max = enchant.getChargesMax(level); - int set = Math.min(Math.abs(charges), max); - PDCUtil.set(item, enchant.getChargesKey(), set); - } - - public static int getExcellentAmount(@NotNull ItemStack item) { - return getExcellents(item).size(); + public static int countCustomEnchantments(@NotNull ItemStack item) { + return getCustomEnchantments(item).size(); } @NotNull - public static Map getExcellents(@NotNull ItemStack item) { - return getExcellents(getAll(item)); + public static Map getCustomEnchantments(@NotNull ItemStack item) { + return toCustomEnchantments(getEnchantments(item)); } @NotNull - public static Map getExcellents(@NotNull ItemMeta meta) { - return getExcellents(getAll(meta)); + public static Map getCustomEnchantments(@NotNull ItemMeta meta) { + return toCustomEnchantments(getEnchantments(meta)); } @NotNull - private static Map getExcellents(@NotNull Map enchants) { - Map map = new HashMap<>(); + private static Map toCustomEnchantments(@NotNull Map enchants) { + Map map = new HashMap<>(); enchants.forEach((enchantment, level) -> { - ExcellentEnchant excellent = EnchantRegistry.getByKey(enchantment.getKey()); + EnchantmentData excellent = EnchantRegistry.getByKey(enchantment.getKey()); if (excellent != null) { map.put(excellent, level); } @@ -331,15 +264,15 @@ public class EnchantUtils { } @NotNull - public static Map getExcellents(@NotNull ItemStack item, @NotNull Class clazz) { + public static Map getCustomEnchantments(@NotNull ItemStack item, @NotNull Class clazz) { Map map = new HashMap<>(); - getAll(item).forEach((enchantment, level) -> { - ExcellentEnchant excellent = EnchantRegistry.getByKey(enchantment.getKey()); - if (excellent == null || !clazz.isAssignableFrom(excellent.getClass())) return; + getEnchantments(item).forEach((enchantment, level) -> { + EnchantmentData enchantmentData = EnchantRegistry.getByKey(enchantment.getKey()); + if (enchantmentData == null || !clazz.isAssignableFrom(enchantmentData.getClass())) return; - map.put(clazz.cast(excellent), level); + map.put(clazz.cast(enchantmentData), level); }); - return map;//CollectionsUtil.sort(map, Comparator.comparing(p -> p.getKey().getPriority(), Comparator.reverseOrder())); + return map; } @NotNull @@ -361,36 +294,36 @@ public class EnchantUtils { } @NotNull - public static Map> getEquipped(@NotNull LivingEntity entity) { - Map> map = new HashMap<>(); + public static Map> getEquipped(@NotNull LivingEntity entity) { + Map> map = new HashMap<>(); getEnchantedEquipment(entity).values().forEach(item -> { - map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getExcellents(item)); + map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getCustomEnchantments(item)); }); return map; } @NotNull - public static Map> getEquipped(@NotNull LivingEntity entity, + public static Map> getEquipped(@NotNull LivingEntity entity, @NotNull Class clazz) { return getEquipped(entity, clazz, EquipmentSlot.values()); } @NotNull - public static Map> getEquipped(@NotNull LivingEntity entity, + public static Map> getEquipped(@NotNull LivingEntity entity, @NotNull Class clazz, @NotNull EquipmentSlot... slots) { Map> map = new HashMap<>(); getEnchantedEquipment(entity, slots).values().forEach(item -> { - map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getExcellents(item, clazz)); + map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getCustomEnchantments(item, clazz)); }); return map; } @NotNull - public static Map getEquipped(@NotNull LivingEntity entity, @NotNull ExcellentEnchant enchantment) { + public static Map getEquipped(@NotNull LivingEntity entity, @NotNull EnchantmentData enchantmentData) { Map map = new HashMap<>(); getEnchantedEquipment(entity).values().forEach(item -> { - int level = getLevel(item, enchantment.getBackend()); + int level = getLevel(item, enchantmentData.getEnchantment()); if (level > 0) { map.put(item, level); } @@ -398,18 +331,32 @@ public class EnchantUtils { return map; } - public static void setSourceWeapon(@NotNull Projectile projectile, @Nullable ItemStack item) { - if (item == null) return; - - projectile.setMetadata(META_PROJECTILE_WEAPON, new FixedMetadataValue(ExcellentEnchantsAPI.PLUGIN, item)); + public static void addEnchantedProjectile(@NotNull Projectile projectile, @Nullable ItemStack item) { + EnchantedProjectile enchantedProjectile = new EnchantedProjectile(projectile, item); + ENCHANTED_PROJECTILE_MAP.put(projectile.getUniqueId(), enchantedProjectile); } @Nullable - public static ItemStack getSourceWeapon(@NotNull Projectile projectile) { - return projectile.hasMetadata(META_PROJECTILE_WEAPON) ? (ItemStack) projectile.getMetadata(META_PROJECTILE_WEAPON).get(0).value() : null; + public static EnchantedProjectile getEnchantedProjectile(@NotNull Projectile projectile) { + return ENCHANTED_PROJECTILE_MAP.get(projectile.getUniqueId()); } - public static void removeSourceWeapon(@NotNull Projectile projectile) { - projectile.removeMetadata(META_PROJECTILE_WEAPON, ExcellentEnchantsAPI.PLUGIN); + public static void removeEnchantedProjectile(@NotNull Projectile projectile) { + ENCHANTED_PROJECTILE_MAP.remove(projectile.getUniqueId()); + } + + @NotNull + public static Collection getEnchantedProjectiles() { + return ENCHANTED_PROJECTILE_MAP.values(); + } + + public static void setSpawnReason(@NotNull Entity entity, @NotNull CreatureSpawnEvent.SpawnReason reason) { + PDCUtil.set(entity, Keys.entitySpawnReason, reason.name()); + } + + @Nullable + public static CreatureSpawnEvent.SpawnReason getSpawnReason(@NotNull Entity entity) { + String name = PDCUtil.getString(entity, Keys.entitySpawnReason).orElse(null); + return name == null ? null : StringUtil.getEnum(name, CreatureSpawnEvent.SpawnReason.class).orElse(null); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantedProjectile.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantedProjectile.java new file mode 100644 index 0000000..f292ea8 --- /dev/null +++ b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/EnchantedProjectile.java @@ -0,0 +1,63 @@ +package su.nightexpress.excellentenchants.enchantment.util; + +import org.bukkit.entity.Projectile; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant; +import su.nightexpress.nightcore.util.wrapper.UniParticle; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class EnchantedProjectile { + + private final Projectile projectile; + private final ItemStack item; + private final Set particles; + private final Map enchantments; + + public EnchantedProjectile(@NotNull Projectile projectile, @Nullable ItemStack item) { + this.projectile = projectile; + this.item = item; + + this.particles = ConcurrentHashMap.newKeySet(); + this.enchantments = new HashMap<>(); + } + + public boolean isValid() { + return this.projectile.isValid() && !this.projectile.isDead(); + } + + public void playParticles() { + this.particles.forEach(entry -> { + entry.play(this.projectile.getLocation(), 0f, 0f, 10); + }); + } + + public void addParticle(@NotNull UniParticle particle) { + this.particles.add(particle); + } + + @NotNull + public Projectile getProjectile() { + return projectile; + } + + @Nullable + public ItemStack getItem() { + return item; + } + + @NotNull + public Set getParticles() { + return particles; + } + + @NotNull + public Map getEnchantments() { + return enchantments; + } +} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/Evaluator.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/Evaluator.java deleted file mode 100644 index 00a4e18..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/Evaluator.java +++ /dev/null @@ -1,94 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.util; - -import org.jetbrains.annotations.NotNull; - -public class Evaluator { - - public static double evaluate(@NotNull final String str) { - return new Object() { - int pos = -1, ch; - - void nextChar() { - ch = (++pos < str.length()) ? str.charAt(pos) : -1; - } - - boolean eat(int charToEat) { - while (ch == ' ') nextChar(); - if (ch == charToEat) { - nextChar(); - return true; - } - return false; - } - - double parse() { - nextChar(); - double x = parseExpression(); - if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch); - return x; - } - - // Grammar: - // expression = term | expression `+` term | expression `-` term - // term = factor | term `*` factor | term `/` factor - // factor = `+` factor | `-` factor | `(` expression `)` | number - // | functionName `(` expression `)` | functionName factor - // | factor `^` factor - - double parseExpression() { - double x = parseTerm(); - for (;;) { - if (eat('+')) x += parseTerm(); // addition - else if (eat('-')) x -= parseTerm(); // subtraction - else return x; - } - } - - double parseTerm() { - double x = parseFactor(); - for (;;) { - if (eat('*')) x *= parseFactor(); // multiplication - else if (eat('/')) x /= parseFactor(); // division - else return x; - } - } - - double parseFactor() { - if (eat('+')) return +parseFactor(); // unary plus - if (eat('-')) return -parseFactor(); // unary minus - - double x; - int startPos = this.pos; - if (eat('(')) { // parentheses - x = parseExpression(); - if (!eat(')')) throw new RuntimeException("Missing ')'"); - } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers - while ((ch >= '0' && ch <= '9') || ch == '.') nextChar(); - x = Double.parseDouble(str.substring(startPos, this.pos)); - } else if (ch >= 'a' && ch <= 'z') { // functions - while (ch >= 'a' && ch <= 'z') nextChar(); - String func = str.substring(startPos, this.pos); - if (eat('(')) { - x = parseExpression(); - if (!eat(')')) throw new RuntimeException("Missing ')' after argument to " + func); - } else { - x = parseFactor(); - } - x = switch (func) { - case "sqrt" -> Math.sqrt(x); - case "sin" -> Math.sin(Math.toRadians(x)); - case "cos" -> Math.cos(Math.toRadians(x)); - case "tan" -> Math.tan(Math.toRadians(x)); - default -> throw new RuntimeException("Unknown function: " + func); - }; - } else { - throw new RuntimeException("Unexpected: " + (char)ch); - } - - if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation - - return x; - } - }.parse(); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/Modifier.java b/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/Modifier.java deleted file mode 100644 index 5353180..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/enchantment/util/Modifier.java +++ /dev/null @@ -1,69 +0,0 @@ -package su.nightexpress.excellentenchants.enchantment.util; - -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JOption; -import su.nexmedia.engine.api.config.JYML; - -public class Modifier { - - private final double base; - private final double perLevel; - private final ModifierAction action; - - public Modifier(double base, double perLevel, @NotNull ModifierAction action) { - this.base = base; - this.perLevel = perLevel; - this.action = action; - } - - @NotNull - public static Modifier add(double base, double perLevel) { - return new Modifier(base, perLevel, ModifierAction.ADD); - } - - @NotNull - public static Modifier multiply(double base, double perLevel) { - return new Modifier(base, perLevel, ModifierAction.MULTIPLY); - } - - @NotNull - public static Modifier read(@NotNull JYML cfg, @NotNull String path, @NotNull Modifier def, @NotNull String... comments) { - return new JOption<>(path, - (cfg2, path2, def2) -> read(cfg2, path2), - def, - comments - ).setWriter((cfg2, path2, mod) -> mod.write(cfg2, path2)).read(cfg); - } - - @NotNull - public static Modifier read(@NotNull JYML cfg, @NotNull String path) { - double base = JOption.create(path + ".Base", 0D).read(cfg); - double perLevel = JOption.create(path + ".Per_Level", 0D).read(cfg); - ModifierAction action = JOption.create(path + ".Action", ModifierAction.class, ModifierAction.ADD).read(cfg); - - return new Modifier(base, perLevel, action); - } - - public void write(@NotNull JYML cfg, @NotNull String path) { - cfg.set(path + ".Base", this.getBase()); - cfg.set(path + ".Per_Level", this.getPerLevel()); - cfg.set(path + ".Action", this.getAction().name()); - } - - public double getValue(int level) { - return this.action.math(this.getBase(), this.getPerLevel() * level); - } - - public double getBase() { - return base; - } - - public double getPerLevel() { - return perLevel; - } - - @NotNull - public ModifierAction getAction() { - return action; - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/NoCheatPlusHook.java b/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/NoCheatPlusHook.java index 9cc6458..8b9900c 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/NoCheatPlusHook.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/NoCheatPlusHook.java @@ -5,19 +5,19 @@ import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.hooks.ExemptionContext; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.utils.EngineUtils; import su.nightexpress.excellentenchants.hook.HookId; +import su.nightexpress.nightcore.util.Plugins; public class NoCheatPlusHook { public static void exemptBlocks(@NotNull Player player) { - if (!EngineUtils.hasPlugin(HookId.NCP)) return; + if (!Plugins.isLoaded(HookId.NCP)) return; NCPAPIProvider.getNoCheatPlusAPI().getPlayerDataManager().getPlayerData(player).exempt(CheckType.BLOCKBREAK, ExemptionContext.ANONYMOUS_NESTED); } public static void unexemptBlocks(@NotNull Player player) { - if (!EngineUtils.hasPlugin(HookId.NCP)) return; + if (!Plugins.isLoaded(HookId.NCP)) return; NCPAPIProvider.getNoCheatPlusAPI().getPlayerDataManager().getPlayerData(player).unexempt(CheckType.BLOCKBREAK, ExemptionContext.ANONYMOUS_NESTED); } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/PlaceholderHook.java b/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/PlaceholderHook.java index 739e839..9674ab1 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/PlaceholderHook.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/PlaceholderHook.java @@ -7,17 +7,17 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.StringUtil; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.ExcellentEnchantsAPI; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.enchantment.registry.EnchantRegistry; +import su.nightexpress.nightcore.util.NumberUtil; +import su.nightexpress.nightcore.util.StringUtil; public class PlaceholderHook { private static EnchantsExpansion expansion; - public static void setup(@NotNull ExcellentEnchants plugin) { + public static void setup(@NotNull ExcellentEnchantsPlugin plugin) { if (expansion == null) { expansion = new EnchantsExpansion(plugin); expansion.register(); @@ -33,9 +33,9 @@ public class PlaceholderHook { static class EnchantsExpansion extends PlaceholderExpansion { - private final ExcellentEnchants plugin; + private final ExcellentEnchantsPlugin plugin; - public EnchantsExpansion(@NotNull ExcellentEnchants plugin) { + public EnchantsExpansion(@NotNull ExcellentEnchantsPlugin plugin) { this.plugin = plugin; } @@ -75,22 +75,24 @@ public class PlaceholderHook { ItemStack item = player.getInventory().getItem(slot); if (item == null || item.getType().isAir()) return "-"; - ExcellentEnchant enchant = EnchantRegistry.getByKey(NamespacedKey.minecraft(chargesSplit[1].toLowerCase())); + EnchantmentData enchant = EnchantRegistry.getByKey(NamespacedKey.minecraft(chargesSplit[1].toLowerCase())); if (enchant == null) return null; return String.valueOf(enchant.getCharges(item)); } + if (params.startsWith("charges_maximum_")) { String[] chargesSplit = params.substring("charges_maximum_".length()).split(":"); if (chargesSplit.length < 2) return null; - ExcellentEnchant enchant = EnchantRegistry.getByKey(NamespacedKey.minecraft(chargesSplit[0].toLowerCase())); + EnchantmentData enchant = EnchantRegistry.getByKey(NamespacedKey.minecraft(chargesSplit[0].toLowerCase())); if (enchant == null) return null; - int level = StringUtil.getInteger(chargesSplit[1], 1); + int level = NumberUtil.getInteger(chargesSplit[1], 1); return String.valueOf(enchant.getChargesMax(level)); } + return super.onPlaceholderRequest(player, params); } } diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/ProtocolHook.java b/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/ProtocolHook.java index 6e0fc84..6273bd0 100644 --- a/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/ProtocolHook.java +++ b/Core/src/main/java/su/nightexpress/excellentenchants/hook/impl/ProtocolHook.java @@ -11,10 +11,10 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.MerchantRecipe; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nightexpress.excellentenchants.ExcellentEnchantsAPI; -import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant; +import su.nightexpress.excellentenchants.ExcellentEnchantsPlugin; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils; import java.util.*; @@ -24,11 +24,11 @@ public class ProtocolHook { private static boolean isRegistered = false; - public static void setup() { + public static void setup(@NotNull ExcellentEnchantsPlugin plugin) { if (isRegistered) return; ProtocolManager manager = ProtocolLibrary.getProtocolManager(); - manager.addPacketListener(new PacketAdapter(ExcellentEnchantsAPI.PLUGIN, PacketType.Play.Server.SET_SLOT) { + manager.addPacketListener(new PacketAdapter(plugin, PacketType.Play.Server.SET_SLOT) { @Override public void onPacketSending(PacketEvent event) { PacketContainer packet = event.getPacket(); @@ -39,7 +39,7 @@ public class ProtocolHook { } }); - manager.addPacketListener(new PacketAdapter(ExcellentEnchantsAPI.PLUGIN, PacketType.Play.Server.WINDOW_ITEMS) { + manager.addPacketListener(new PacketAdapter(plugin, PacketType.Play.Server.WINDOW_ITEMS) { @Override public void onPacketSending(PacketEvent event) { PacketContainer packet = event.getPacket(); @@ -47,15 +47,12 @@ public class ProtocolHook { List items = packet.getItemListModifier().readSafely(0); boolean isCreative = event.getPlayer().getGameMode() == GameMode.CREATIVE; - for (int index = 0; index < items.size(); index++) { - ItemStack item = items.get(index); - items.set(index, update(item, isCreative)); - } + items.replaceAll(itemStack -> update(itemStack, isCreative)); packet.getItemListModifier().write(0, items); } }); - manager.addPacketListener(new PacketAdapter(ExcellentEnchantsAPI.PLUGIN, PacketType.Play.Server.OPEN_WINDOW_MERCHANT) { + manager.addPacketListener(new PacketAdapter(plugin, PacketType.Play.Server.OPEN_WINDOW_MERCHANT) { @Override public void onPacketSending(PacketEvent event) { PacketContainer packet = event.getPacket(); @@ -85,28 +82,29 @@ public class ProtocolHook { ItemMeta meta = copy.getItemMeta(); if (meta == null || meta.hasItemFlag(ItemFlag.HIDE_ENCHANTS)) return item; - Map enchants = EnchantUtils.getExcellents(meta) + Map enchants = EnchantUtils.getCustomEnchantments(meta) .entrySet().stream() - .sorted(Comparator.comparing(e -> e.getKey().getTier().getPriority())) + .sorted(Comparator.comparing((Map.Entry entry) -> entry.getKey().getRarity().getWeight()) + .thenComparing(entry -> entry.getKey().getName())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (old,nev) -> nev, LinkedHashMap::new)); if (enchants.isEmpty()) return item; List lore = meta.getLore() == null ? new ArrayList<>() : meta.getLore(); if (!lore.isEmpty()) { - enchants.keySet().forEach(enchant -> lore.removeIf(line -> line.contains(enchant.getDisplayName()))); + enchants.keySet().forEach(enchant -> lore.removeIf(line -> line.contains(enchant.getName()))); if (isCreative) { enchants.forEach((enchant, level) -> { - lore.removeAll(enchant.formatDescription(level)); + lore.removeAll(enchant.getDescriptionReplaced(level)); }); } } if (EnchantUtils.canHaveDescription(item) && !isCreative) { enchants.forEach((enchant, level) -> { - lore.addAll(0, enchant.formatDescription(level)); + lore.addAll(0, enchant.getDescriptionReplaced(level)); }); } enchants.forEach((enchant, level) -> { - int charges = EnchantUtils.getCharges(meta, enchant); + int charges = enchant.getCharges(meta); lore.add(0, enchant.getNameFormatted(level, charges)); }); diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/tier/Tier.java b/Core/src/main/java/su/nightexpress/excellentenchants/tier/Tier.java deleted file mode 100644 index 89bc372..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/tier/Tier.java +++ /dev/null @@ -1,84 +0,0 @@ -package su.nightexpress.excellentenchants.tier; - -import org.jetbrains.annotations.NotNull; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.api.placeholder.PlaceholderMap; -import su.nexmedia.engine.utils.Colorizer; -import su.nexmedia.engine.utils.NumberUtil; -import su.nightexpress.excellentenchants.Placeholders; -import su.nightexpress.excellentenchants.api.enchantment.ITier; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; - -import java.util.Map; - -public class Tier implements ITier { - - private final String id; - private final int priority; - private final String name; - private final String color; - private final Map chance; - private final PlaceholderMap placeholderMap; - - public Tier(@NotNull String id, int priority, @NotNull String name, @NotNull String color, - @NotNull Map chance) { - this.id = id.toLowerCase(); - this.priority = priority; - this.name = Colorizer.apply(name); - this.color = Colorizer.apply(color); - this.chance = chance; - this.placeholderMap = new PlaceholderMap() - .add(Placeholders.TIER_ID, this::getId) - .add(Placeholders.TIER_NAME, this::getName) - .add(Placeholders.TIER_OBTAIN_CHANCE_ENCHANTING, () -> NumberUtil.format(this.getChance(ObtainType.ENCHANTING))) - .add(Placeholders.TIER_OBTAIN_CHANCE_VILLAGER, () -> NumberUtil.format(this.getChance(ObtainType.VILLAGER))) - .add(Placeholders.TIER_OBTAIN_CHANCE_LOOT_GENERATION, () -> NumberUtil.format(this.getChance(ObtainType.LOOT_GENERATION))) - .add(Placeholders.TIER_OBTAIN_CHANCE_FISHING, () -> NumberUtil.format(this.getChance(ObtainType.FISHING))) - .add(Placeholders.TIER_OBTAIN_CHANCE_MOB_SPAWNING, () -> NumberUtil.format(this.getChance(ObtainType.MOB_SPAWNING))) - ; - } - - public void write(@NotNull JYML cfg, @NotNull String path) { - cfg.set(path + ".Name", this.getName()); - cfg.set(path + ".Color", this.getColor()); - cfg.set(path + ".Priority", this.getPriority()); - cfg.remove(path + ".Obtain_Chance"); - this.getChance().forEach((type, chance) -> { - cfg.set(path + ".Obtain_Chance." + type.name(), chance); - }); - } - - @Override - @NotNull - public PlaceholderMap getPlaceholders() { - return this.placeholderMap; - } - - @NotNull - public String getId() { - return this.id; - } - - public int getPriority() { - return priority; - } - - @NotNull - public String getName() { - return this.getColor() + this.name; - } - - @NotNull - public String getColor() { - return this.color; - } - - @NotNull - public Map getChance() { - return this.chance; - } - - public double getChance(@NotNull ObtainType obtainType) { - return this.getChance().getOrDefault(obtainType, 0D); - } -} diff --git a/Core/src/main/java/su/nightexpress/excellentenchants/tier/TierManager.java b/Core/src/main/java/su/nightexpress/excellentenchants/tier/TierManager.java deleted file mode 100644 index 8e0d7ae..0000000 --- a/Core/src/main/java/su/nightexpress/excellentenchants/tier/TierManager.java +++ /dev/null @@ -1,119 +0,0 @@ -package su.nightexpress.excellentenchants.tier; - -import net.md_5.bungee.api.ChatColor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.api.config.JYML; -import su.nexmedia.engine.api.manager.AbstractManager; -import su.nexmedia.engine.utils.Colors2; -import su.nexmedia.engine.utils.random.Rnd; -import su.nightexpress.excellentenchants.ExcellentEnchants; -import su.nightexpress.excellentenchants.config.Config; -import su.nightexpress.excellentenchants.api.enchantment.ObtainType; - -import java.util.*; -import java.util.stream.Collectors; - -public class TierManager extends AbstractManager { - - public static final String FILE_NAME = "tiers.yml"; - - private final Map tierMap; - - public TierManager(@NotNull ExcellentEnchants plugin) { - super(plugin); - this.tierMap = new HashMap<>(); - } - - @Override - protected void onLoad() { - JYML config = this.getConfig(); - - if (config.getSection("").isEmpty()) { - Config.getDefaultTiers().forEach(tier -> tier.write(config, tier.getId())); - } - - for (String sId : config.getSection("")) { - String path = sId + "."; - - int priority = config.getInt(path + "Priority"); - String name = config.getString(path + "Name", sId); - String color = config.getString(path + "Color", Colors2.WHITE); - - ChatColor chatColor = ChatColor.of(color); - if (chatColor != null) { - color = chatColor.toString(); - } - - Map chance = new HashMap<>(); - for (ObtainType obtainType : ObtainType.values()) { - config.addMissing(path + "Obtain_Chance." + obtainType.name(), 50D); - - double chanceType = config.getDouble(path + "Obtain_Chance." + obtainType.name()); - chance.put(obtainType, chanceType); - } - - Tier tier = new Tier(sId, priority, name, color, chance); - this.tierMap.put(tier.getId(), tier); - } - config.saveChanges(); - - this.plugin.info("Tiers Loaded: " + this.tierMap.size()); - } - - @Override - protected void onShutdown() { - this.tierMap.clear(); - } - - @NotNull - public JYML getConfig() { - return JYML.loadOrExtract(plugin, FILE_NAME); - } - - @NotNull - public Map getTierMap() { - return tierMap; - } - - @NotNull - public Collection getTiers() { - return this.getTierMap().values(); - } - - @Nullable - public Tier getTierById(@NotNull String id) { - return this.getTierMap().get(id.toLowerCase()); - } - - @NotNull - public List getTierIds() { - return new ArrayList<>(this.getTierMap().keySet()); - } - - @Nullable - public Tier getTierByChance(@NotNull ObtainType obtainType) { - Map map = this.getTiers().stream() - .filter(tier -> tier.getChance(obtainType) > 0D) - .collect(Collectors.toMap(k -> k, v -> v.getChance(obtainType), (o, n) -> n, HashMap::new)); - if (map.isEmpty()) return null; - - return Rnd.getByWeight(map); - } - - @NotNull - public Tier getMostCommon() { - return this.getTiers().stream().min(Comparator.comparingInt(Tier::getPriority)).orElseThrow(); - } - - @NotNull - public Tier getByRarityModifier(double point) { - int minPriority = this.getTiers().stream().mapToInt(Tier::getPriority).min().orElse(0); - int maxPriority = this.getTiers().stream().mapToInt(Tier::getPriority).max().orElse(0); - - int threshold = (int) Math.ceil(minPriority + (maxPriority - minPriority) * point); - - return this.getTiers().stream().filter(tier -> tier.getPriority() <= threshold) - .max(Comparator.comparingInt(tier -> tier.getPriority() - threshold)).orElse(this.getMostCommon()); - } -} diff --git a/Core/src/main/resources/config.yml b/Core/src/main/resources/config.yml deleted file mode 100644 index 9fa4a0a..0000000 --- a/Core/src/main/resources/config.yml +++ /dev/null @@ -1,2 +0,0 @@ -Plugin: - Command_Aliases: 'excellentenchants,eenchants' \ No newline at end of file diff --git a/Core/src/main/resources/lang/messages_cn.yml b/Core/src/main/resources/lang/messages_cn.yml index ae013c2..d61ea24 100644 --- a/Core/src/main/resources/lang/messages_cn.yml +++ b/Core/src/main/resources/lang/messages_cn.yml @@ -9,10 +9,5 @@ Command: Usage: <玩家> <附魔名> <等级> Desc: 给予自定义附魔书。 Done: 已给予&6%player%&6%enchant%&7附魔书。 - TierBook: - Usage: <玩家> <品质> <等级> - Desc: 给予自定义品质的附魔书 - Error: '&c无效品质!' - Done: 已给予&6%player&6%enchant%&7附魔书。 Error: NoEnchant: '&c没有这种附魔' \ No newline at end of file diff --git a/Core/src/main/resources/plugin.yml b/Core/src/main/resources/plugin.yml index f7eea7d..10e4701 100644 --- a/Core/src/main/resources/plugin.yml +++ b/Core/src/main/resources/plugin.yml @@ -1,9 +1,9 @@ -main: su.nightexpress.excellentenchants.ExcellentEnchants +main: su.nightexpress.excellentenchants.ExcellentEnchantsPlugin version: '${project.version}' name: ExcellentEnchants author: NightExpress -desciption: Vanilla-like enchants for your server. -depend: [ NexEngine ] +desciption: Enchantments that feel like vanilla ones. +depend: [ nightcore ] softdepend: [ ProtocolLib, NoCheatPlus, PlaceholderAPI, MythicMobs ] -api-version: 1.18 +api-version: 1.19 load: STARTUP \ No newline at end of file diff --git a/NMS/pom.xml b/NMS/pom.xml index 7771457..a941bf9 100644 --- a/NMS/pom.xml +++ b/NMS/pom.xml @@ -5,7 +5,7 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 @@ -14,6 +14,7 @@ 17 17 + UTF-8 @@ -32,7 +33,7 @@ su.nightexpress.excellentenchants API - 3.6.5 + 4.0.0 diff --git a/NMS/src/main/java/su/nightexpress/excellentenchants/nms/EnchantNMS.java b/NMS/src/main/java/su/nightexpress/excellentenchants/nms/EnchantNMS.java index ac6c176..8b98472 100644 --- a/NMS/src/main/java/su/nightexpress/excellentenchants/nms/EnchantNMS.java +++ b/NMS/src/main/java/su/nightexpress/excellentenchants/nms/EnchantNMS.java @@ -1,6 +1,7 @@ package su.nightexpress.excellentenchants.nms; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; @@ -8,8 +9,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import java.util.Set; @@ -19,14 +19,13 @@ public interface EnchantNMS { void freezeRegistry(); - void registerEnchantment(@NotNull IEnchantment enchantment); + void registerEnchantment(@NotNull EnchantmentData enchantment); void sendAttackPacket(@NotNull Player player, int id); void retrieveHook(@NotNull FishHook hook, @NotNull ItemStack item); - @Nullable - @Deprecated ItemStack getSpawnEgg(@NotNull LivingEntity entity); + @NotNull Material getItemBlockVariant(@NotNull Material material); @NotNull Set handleFlameWalker(@NotNull LivingEntity entity, @NotNull Location location, int level); diff --git a/V1_18_R2/pom.xml b/V1_18_R2/pom.xml deleted file mode 100644 index e957864..0000000 --- a/V1_18_R2/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - ExcellentEnchants - su.nightexpress.excellentenchants - 3.6.5 - - 4.0.0 - - V1_18_R2 - - - 16 - 16 - - - - - org.spigotmc - spigot - 1.18.2-R0.1-SNAPSHOT - remapped-mojang - - - su.nightexpress.excellentenchants - NMS - 3.6.5 - - - - - - - net.md-5 - specialsource-maven-plugin - 1.2.3 - - - package - - remap - - remap-obf - - org.spigotmc:minecraft-server:1.18.2-R0.1-SNAPSHOT:txt:maps-mojang - true - org.spigotmc:spigot:1.18.2-R0.1-SNAPSHOT:jar:remapped-mojang - true - remapped-obf - - - - package - - remap - - remap-spigot - - ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar - org.spigotmc:minecraft-server:1.18.2-R0.1-SNAPSHOT:csrg:maps-spigot - org.spigotmc:spigot:1.18.2-R0.1-SNAPSHOT:jar:remapped-obf - - - - - - - - \ No newline at end of file diff --git a/V1_18_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_18_R2/V1_18_R2.java b/V1_18_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_18_R2/V1_18_R2.java deleted file mode 100644 index d0fcb92..0000000 --- a/V1_18_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_18_R2/V1_18_R2.java +++ /dev/null @@ -1,134 +0,0 @@ -package su.nightexpress.excellentenchants.nms.v1_18_R2; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.protocol.game.ClientboundAnimatePacket; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.item.SpawnEggItem; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.block.CraftBlock; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftFishHook; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftLivingEntity; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.event.CraftEventFactory; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.Reflex; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; -import su.nightexpress.excellentenchants.nms.EnchantNMS; - -import java.util.HashSet; -import java.util.Set; - -public class V1_18_R2 implements EnchantNMS { - - @Override - public void unfreezeRegistry() { - Reflex.setFieldValue(Enchantment.class, "acceptingNew", true); - } - - @Override - public void freezeRegistry() { - Enchantment.stopAcceptingRegistrations(); - } - - @Override - public void registerEnchantment(@NotNull IEnchantment enchantment) { - Enchantment.registerEnchantment((Enchantment) enchantment); - } - - @Override - public void sendAttackPacket(@NotNull Player player, int id) { - CraftPlayer craftPlayer = (CraftPlayer) player; - Entity entity = craftPlayer.getHandle(); - ClientboundAnimatePacket packet = new ClientboundAnimatePacket(entity, id); - craftPlayer.getHandle().connection.send(packet); - } - - @Override - public void retrieveHook(@NotNull FishHook hook, @NotNull ItemStack item) { - CraftFishHook craftFishHook = (CraftFishHook) hook; - FishingHook handle = craftFishHook.getHandle(); - handle.retrieve(CraftItemStack.asNMSCopy(item)); - } - - @Override - @Nullable - public ItemStack getSpawnEgg(@NotNull LivingEntity entity) { - CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity; - net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle(); - - SpawnEggItem eggItem = SpawnEggItem.byId(livingEntity.getType()); - if (eggItem == null) return null; - - return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance()); - } - - @Override - @NotNull - public Set handleFlameWalker(@NotNull LivingEntity bukkitEntity, @NotNull Location location, int level) { - Entity entity = ((CraftLivingEntity) bukkitEntity).getHandle(); - BlockPos pos = new BlockPos(location.getX(), location.getY(), location.getZ()); - ServerLevel world = ((CraftWorld) bukkitEntity.getWorld()).getHandle(); - - float radius = Math.min(16F, 2F + level); - BlockState bStone = Blocks.MAGMA_BLOCK.defaultBlockState(); - BlockPos.MutableBlockPos posAbove = new BlockPos.MutableBlockPos(); - - Set blocks = new HashSet<>(); - for (BlockPos posNear : BlockPos.betweenClosed(pos.offset(-radius, -1.0, -radius), pos.offset(radius, -1.0, radius))) { - if (!posNear.closerThan(entity.blockPosition(), radius)) continue; - - posAbove.set(posNear.getX(), posNear.getY() + 1, posNear.getZ()); - - BlockState bLavaAbove = world.getBlockState(posAbove); - BlockState bLava = world.getBlockState(posNear); - - if (!bLavaAbove.isAir()) continue; - if (!bLava.getBlock().equals(Blocks.LAVA)) continue; - if (bLava.getValue(LiquidBlock.LEVEL) != 0) continue; - if (!bStone.canSurvive(world, posNear)) continue; - if (!world.isUnobstructed(bStone, posNear, CollisionContext.empty())) continue; - if (!CraftEventFactory.handleBlockFormEvent(world, posNear, bStone, entity)) continue; - //world.scheduleTick(posNear, Blocks.STONE, Rnd.get(60, 120)); - - Location bukkitLoc = new Location(world.getWorld(), posNear.getX(), posNear.getY(), posNear.getZ()); - blocks.add(bukkitLoc.getBlock()); - } - return blocks; - } - - @NotNull - public Item popResource(@NotNull Block block, @NotNull ItemStack item) { - Level world = ((CraftWorld)block.getWorld()).getHandle(); - BlockPos pos = ((CraftBlock)block).getPosition(); - net.minecraft.world.item.ItemStack itemstack = CraftItemStack.asNMSCopy(item); - - float yMod = EntityType.ITEM.getHeight() / 2.0F; - double x = (pos.getX() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D); - double y = (pos.getY() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D) - yMod; - double z = (pos.getZ() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D); - - ItemEntity itemEntity = new ItemEntity(world, x, y, z, itemstack); - itemEntity.setDefaultPickUpDelay(); - return (Item) itemEntity.getBukkitEntity(); - } -} diff --git a/V1_19_R3/pom.xml b/V1_19_R3/pom.xml index 15d35ae..98d45cf 100644 --- a/V1_19_R3/pom.xml +++ b/V1_19_R3/pom.xml @@ -5,15 +5,16 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 V1_19_R3 - 16 - 16 + 17 + 17 + UTF-8 @@ -26,7 +27,7 @@ su.nightexpress.excellentenchants NMS - 3.6.5 + 4.0.0 diff --git a/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/CustomEnchantment.java b/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/CustomEnchantment.java new file mode 100644 index 0000000..8b92ba6 --- /dev/null +++ b/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/CustomEnchantment.java @@ -0,0 +1,137 @@ +package su.nightexpress.excellentenchants.nms.v1_19_R3; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentCategory; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.v1_19_R3.CraftEquipmentSlot; +import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_19_R3.util.CraftNamespacedKey; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions; + +public class CustomEnchantment extends Enchantment { + + private final EnchantmentData enchantmentData; + + private VanillaOptions vanillaOptions; + + public CustomEnchantment(@NotNull EnchantmentData enchantmentData) { + super(nmsRarity(enchantmentData), nmsCategory(enchantmentData), nmsSlots(enchantmentData)); + this.enchantmentData = enchantmentData; + + if (enchantmentData.getDistributionOptions() instanceof VanillaOptions options) { + this.vanillaOptions = options; + } + } + + @Override + public int getMinLevel() { + return this.enchantmentData.getMinLevel(); + } + + @Override + public int getMaxLevel() { + return this.enchantmentData.getMaxLevel(); + } + + @Override + public int getMinCost(int level) { + return this.enchantmentData.getMinCost(level); + } + + @Override + public int getMaxCost(int level) { + return this.enchantmentData.getMaxCost(level); + } + + @Override + protected boolean checkCompatibility(Enchantment other) { + ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(other); + if (location == null) return false; + + NamespacedKey key = CraftNamespacedKey.fromMinecraft(location); + String id = key.getKey(); + + // Expensive probably. + //org.bukkit.enchantments.Enchantment bukkit = CraftEnchantment.minecraftToBukkit(other); + //String id = bukkit.getKey().getKey(); + + return !this.enchantmentData.getConflicts().contains(id); + } + + @Override + public boolean canEnchant(ItemStack item) { + org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item); + if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true; + if (this.enchantmentData.checkItemCategory(bukkitStack)) return true; + + return super.canEnchant(item); + } + + @Override + public boolean isTreasureOnly() { + return this.enchantmentData.isTreasure() || this.isCurse(); + } + + @Override + public boolean isCurse() { + return this.enchantmentData.isCurse(); + } + + @Override + public boolean isTradeable() { + return this.vanillaOptions != null && this.vanillaOptions.isTradeable(); + } + + @Override + public boolean isDiscoverable() { + return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable(); + } + + public static Rarity nmsRarity(@NotNull EnchantmentData data) { + return switch (data.getRarity()) { + case RARE -> Rarity.RARE; + case COMMON -> Rarity.COMMON; + case UNCOMMON -> Rarity.UNCOMMON; + case VERY_RARE -> Rarity.VERY_RARE; + }; + } + + @NotNull + public static EnchantmentCategory nmsCategory(@NotNull EnchantmentData data) { + return switch (data.getCategory()) { + case WEAPON -> EnchantmentCategory.WEAPON; + case TOOL -> EnchantmentCategory.DIGGER; + case ARMOR -> EnchantmentCategory.ARMOR; + case BOW -> EnchantmentCategory.BOW; + case TRIDENT -> EnchantmentCategory.TRIDENT; + case CROSSBOW -> EnchantmentCategory.CROSSBOW; + case WEARABLE -> EnchantmentCategory.WEARABLE; + case BREAKABLE -> EnchantmentCategory.BREAKABLE; + case ARMOR_FEET -> EnchantmentCategory.ARMOR_FEET; + case ARMOR_HEAD -> EnchantmentCategory.ARMOR_HEAD; + case ARMOR_LEGS -> EnchantmentCategory.ARMOR_LEGS; + case ARMOR_TORSO -> EnchantmentCategory.ARMOR_CHEST; + case VANISHABLE -> EnchantmentCategory.VANISHABLE; + case FISHING_ROD -> EnchantmentCategory.FISHING_ROD; + default -> throw new IllegalStateException("Unexpected value: " + data.getCategory()); + }; + } + + public static EquipmentSlot[] nmsSlots(@NotNull EnchantmentData data) { + org.bukkit.inventory.EquipmentSlot[] slots = data.getSlots(); + EquipmentSlot[] nmsSlots = new EquipmentSlot[slots.length]; + + for (int index = 0; index < nmsSlots.length; index++) { + org.bukkit.inventory.EquipmentSlot bukkitSlot = slots[index]; + nmsSlots[index] = CraftEquipmentSlot.getNMS(bukkitSlot); + } + + return nmsSlots; + } +} diff --git a/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/V1_19_R3.java b/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/V1_19_R3.java index f0ce0a6..2215024 100644 --- a/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/V1_19_R3.java +++ b/V1_19_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_19_R3/V1_19_R3.java @@ -1,6 +1,8 @@ package su.nightexpress.excellentenchants.nms.v1_19_R3; import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.protocol.game.ClientboundAnimatePacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; @@ -8,21 +10,24 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock; +import org.bukkit.craftbukkit.v1_19_R3.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftFishHook; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_19_R3.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_19_R3.util.CraftMagicNumbers; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; @@ -30,29 +35,37 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.Reflex; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.nms.EnchantNMS; +import su.nightexpress.nightcore.util.Reflex; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Set; public class V1_19_R3 implements EnchantNMS { @Override public void unfreezeRegistry() { + Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "l", false); + Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "m", new IdentityHashMap<>()); Reflex.setFieldValue(Enchantment.class, "acceptingNew", true); } @Override public void freezeRegistry() { Enchantment.stopAcceptingRegistrations(); + BuiltInRegistries.ENCHANTMENT.freeze(); } @Override - public void registerEnchantment(@NotNull IEnchantment enchantment) { - Enchantment.registerEnchantment((Enchantment) enchantment); + public void registerEnchantment(@NotNull EnchantmentData data) { + CustomEnchantment customEnchantment = new CustomEnchantment(data); + Registry.register(BuiltInRegistries.ENCHANTMENT, data.getId(), customEnchantment); + + CraftEnchantment craftEnchantment = new CraftEnchantment(customEnchantment); + Enchantment.registerEnchantment(craftEnchantment); + data.setEnchantment(craftEnchantment); } @Override @@ -70,16 +83,15 @@ public class V1_19_R3 implements EnchantNMS { handle.retrieve(CraftItemStack.asNMSCopy(item)); } + @NotNull @Override - @Nullable - public ItemStack getSpawnEgg(@NotNull LivingEntity entity) { - CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity; - net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle(); - - SpawnEggItem eggItem = SpawnEggItem.byId(livingEntity.getType()); - if (eggItem == null) return null; - - return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance()); + public Material getItemBlockVariant(@NotNull Material material) { + ItemStack itemStack = new ItemStack(material); + net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + if (nmsStack.getItem() instanceof BlockItem blockItem) { + return CraftMagicNumbers.getMaterial(blockItem.getBlock()); + } + return material; } @Override diff --git a/V1_20_R1/pom.xml b/V1_20_R1/pom.xml index 0a2254b..01305e5 100644 --- a/V1_20_R1/pom.xml +++ b/V1_20_R1/pom.xml @@ -5,7 +5,7 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 @@ -14,6 +14,7 @@ 17 17 + UTF-8 @@ -26,7 +27,7 @@ su.nightexpress.excellentenchants NMS - 3.6.5 + 4.0.0 diff --git a/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/CustomEnchantment.java b/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/CustomEnchantment.java new file mode 100644 index 0000000..ad8f54f --- /dev/null +++ b/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/CustomEnchantment.java @@ -0,0 +1,137 @@ +package su.nightexpress.excellentenchants.nms.v1_20_R1; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentCategory; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.v1_20_R1.CraftEquipmentSlot; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R1.util.CraftNamespacedKey; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions; + +public class CustomEnchantment extends Enchantment { + + private final EnchantmentData enchantmentData; + + private VanillaOptions vanillaOptions; + + public CustomEnchantment(@NotNull EnchantmentData enchantmentData) { + super(nmsRarity(enchantmentData), nmsCategory(enchantmentData), nmsSlots(enchantmentData)); + this.enchantmentData = enchantmentData; + + if (enchantmentData.getDistributionOptions() instanceof VanillaOptions options) { + this.vanillaOptions = options; + } + } + + @Override + public int getMinLevel() { + return this.enchantmentData.getMinLevel(); + } + + @Override + public int getMaxLevel() { + return this.enchantmentData.getMaxLevel(); + } + + @Override + public int getMinCost(int level) { + return this.enchantmentData.getMinCost(level); + } + + @Override + public int getMaxCost(int level) { + return this.enchantmentData.getMaxCost(level); + } + + @Override + protected boolean checkCompatibility(Enchantment other) { + ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(other); + if (location == null) return false; + + NamespacedKey key = CraftNamespacedKey.fromMinecraft(location); + String id = key.getKey(); + + // Expensive probably. + //org.bukkit.enchantments.Enchantment bukkit = CraftEnchantment.minecraftToBukkit(other); + //String id = bukkit.getKey().getKey(); + + return !this.enchantmentData.getConflicts().contains(id); + } + + @Override + public boolean canEnchant(ItemStack item) { + org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item); + if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true; + if (this.enchantmentData.checkItemCategory(bukkitStack)) return true; + + return super.canEnchant(item); + } + + @Override + public boolean isTreasureOnly() { + return this.enchantmentData.isTreasure() || this.isCurse(); + } + + @Override + public boolean isCurse() { + return this.enchantmentData.isCurse(); + } + + @Override + public boolean isTradeable() { + return this.vanillaOptions != null && this.vanillaOptions.isTradeable(); + } + + @Override + public boolean isDiscoverable() { + return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable(); + } + + public static Rarity nmsRarity(@NotNull EnchantmentData data) { + return switch (data.getRarity()) { + case RARE -> Rarity.RARE; + case COMMON -> Rarity.COMMON; + case UNCOMMON -> Rarity.UNCOMMON; + case VERY_RARE -> Rarity.VERY_RARE; + }; + } + + @NotNull + public static EnchantmentCategory nmsCategory(@NotNull EnchantmentData data) { + return switch (data.getCategory()) { + case WEAPON -> EnchantmentCategory.WEAPON; + case TOOL -> EnchantmentCategory.DIGGER; + case ARMOR -> EnchantmentCategory.ARMOR; + case BOW -> EnchantmentCategory.BOW; + case TRIDENT -> EnchantmentCategory.TRIDENT; + case CROSSBOW -> EnchantmentCategory.CROSSBOW; + case WEARABLE -> EnchantmentCategory.WEARABLE; + case BREAKABLE -> EnchantmentCategory.BREAKABLE; + case ARMOR_FEET -> EnchantmentCategory.ARMOR_FEET; + case ARMOR_HEAD -> EnchantmentCategory.ARMOR_HEAD; + case ARMOR_LEGS -> EnchantmentCategory.ARMOR_LEGS; + case ARMOR_TORSO -> EnchantmentCategory.ARMOR_CHEST; + case VANISHABLE -> EnchantmentCategory.VANISHABLE; + case FISHING_ROD -> EnchantmentCategory.FISHING_ROD; + default -> throw new IllegalStateException("Unexpected value: " + data.getCategory()); + }; + } + + public static EquipmentSlot[] nmsSlots(@NotNull EnchantmentData data) { + org.bukkit.inventory.EquipmentSlot[] slots = data.getSlots(); + EquipmentSlot[] nmsSlots = new EquipmentSlot[slots.length]; + + for (int index = 0; index < nmsSlots.length; index++) { + org.bukkit.inventory.EquipmentSlot bukkitSlot = slots[index]; + nmsSlots[index] = CraftEquipmentSlot.getNMS(bukkitSlot); + } + + return nmsSlots; + } +} diff --git a/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/V1_20_R1.java b/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/V1_20_R1.java index fada7a4..64abab8 100644 --- a/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/V1_20_R1.java +++ b/V1_20_R1/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R1/V1_20_R1.java @@ -1,6 +1,8 @@ package su.nightexpress.excellentenchants.nms.v1_20_R1; import net.minecraft.core.BlockPos; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.protocol.game.ClientboundAnimatePacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -9,21 +11,24 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock; +import org.bukkit.craftbukkit.v1_20_R1.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftFishHook; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R1.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R1.util.CraftMagicNumbers; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; @@ -31,29 +36,37 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.Reflex; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.nms.EnchantNMS; +import su.nightexpress.nightcore.util.Reflex; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Set; public class V1_20_R1 implements EnchantNMS { @Override public void unfreezeRegistry() { + Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "l", false); + Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "m", new IdentityHashMap<>()); Reflex.setFieldValue(Enchantment.class, "acceptingNew", true); } @Override public void freezeRegistry() { Enchantment.stopAcceptingRegistrations(); + BuiltInRegistries.ENCHANTMENT.freeze(); } @Override - public void registerEnchantment(@NotNull IEnchantment enchantment) { - Enchantment.registerEnchantment((Enchantment) enchantment); + public void registerEnchantment(@NotNull EnchantmentData data) { + CustomEnchantment customEnchantment = new CustomEnchantment(data); + Registry.register(BuiltInRegistries.ENCHANTMENT, data.getId(), customEnchantment); + + CraftEnchantment craftEnchantment = new CraftEnchantment(customEnchantment); + Enchantment.registerEnchantment(craftEnchantment); + data.setEnchantment(craftEnchantment); } @Override @@ -71,16 +84,15 @@ public class V1_20_R1 implements EnchantNMS { handle.retrieve(CraftItemStack.asNMSCopy(item)); } + @NotNull @Override - @Nullable - public ItemStack getSpawnEgg(@NotNull LivingEntity entity) { - CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity; - net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle(); - - SpawnEggItem eggItem = SpawnEggItem.byId(livingEntity.getType()); - if (eggItem == null) return null; - - return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance()); + public Material getItemBlockVariant(@NotNull Material material) { + ItemStack itemStack = new ItemStack(material); + net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + if (nmsStack.getItem() instanceof BlockItem blockItem) { + return CraftMagicNumbers.getMaterial(blockItem.getBlock()); + } + return material; } @Override diff --git a/V1_20_R2/pom.xml b/V1_20_R2/pom.xml index 4ef93cd..51f0fed 100644 --- a/V1_20_R2/pom.xml +++ b/V1_20_R2/pom.xml @@ -5,7 +5,7 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 @@ -14,6 +14,7 @@ 17 17 + UTF-8 @@ -26,7 +27,7 @@ su.nightexpress.excellentenchants NMS - 3.6.5 + 4.0.0 diff --git a/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/V1_20_R2.java b/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/V1_20_R2.java deleted file mode 100644 index 333b2e4..0000000 --- a/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/V1_20_R2.java +++ /dev/null @@ -1,116 +0,0 @@ -package su.nightexpress.excellentenchants.nms; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.protocol.game.ClientboundAnimatePacket; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.item.SpawnEggItem; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftFishHook; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftLivingEntity; -import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory; -import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; -import org.bukkit.entity.FishHook; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; -import java.util.Set; - -public class V1_20_R2 implements EnchantNMS { - - @Override - public void sendAttackPacket(@NotNull Player player, int id) { - CraftPlayer craftPlayer = (CraftPlayer) player; - ServerPlayer entity = craftPlayer.getHandle(); - ClientboundAnimatePacket packet = new ClientboundAnimatePacket(entity, id); - craftPlayer.getHandle().connection.send(packet); - } - - @Override - public void retrieveHook(@NotNull FishHook hook, @NotNull ItemStack item) { - CraftFishHook craftFishHook = (CraftFishHook) hook; - FishingHook handle = craftFishHook.getHandle(); - handle.retrieve(CraftItemStack.asNMSCopy(item)); - } - - @Override - @Nullable - public ItemStack getSpawnEgg(@NotNull LivingEntity entity) { - CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity; - net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle(); - - SpawnEggItem eggItem = SpawnEggItem.byId(livingEntity.getType()); - if (eggItem == null) return null; - - return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance()); - } - - @Override - @NotNull - public Set handleFlameWalker(@NotNull LivingEntity bukkitEntity, @NotNull Location location, int level) { - Entity entity = ((CraftLivingEntity) bukkitEntity).getHandle(); - BlockPos pos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - ServerLevel world = ((CraftWorld) bukkitEntity.getWorld()).getHandle(); - - int radius = Math.min(16, 2 + level); - BlockState bStone = Blocks.MAGMA_BLOCK.defaultBlockState(); - BlockPos.MutableBlockPos posAbove = new BlockPos.MutableBlockPos(); - - Set blocks = new HashSet<>(); - for (BlockPos posNear : BlockPos.betweenClosed(pos.offset(-radius, -1, -radius), pos.offset(radius, -1, radius))) { - if (!posNear.closerThan(entity.blockPosition(), radius)) continue; - - posAbove.set(posNear.getX(), posNear.getY() + 1, posNear.getZ()); - - BlockState bLavaAbove = world.getBlockState(posAbove); - BlockState bLava = world.getBlockState(posNear); - - if (!bLavaAbove.isAir()) continue; - if (!bLava.getBlock().equals(Blocks.LAVA)) continue; - if (bLava.getValue(LiquidBlock.LEVEL) != 0) continue; - if (!bStone.canSurvive(world, posNear)) continue; - if (!world.isUnobstructed(bStone, posNear, CollisionContext.empty())) continue; - if (!CraftEventFactory.handleBlockFormEvent(world, posNear, bStone, entity)) continue; - //world.scheduleTick(posNear, Blocks.STONE, Rnd.get(60, 120)); - - Location bukkitLoc = new Location(world.getWorld(), posNear.getX(), posNear.getY(), posNear.getZ()); - blocks.add(bukkitLoc.getBlock()); - } - return blocks; - } - - @NotNull - public Item popResource(@NotNull Block block, @NotNull ItemStack item) { - Level world = ((CraftWorld)block.getWorld()).getHandle(); - BlockPos pos = ((CraftBlock)block).getPosition(); - net.minecraft.world.item.ItemStack itemstack = CraftItemStack.asNMSCopy(item); - - float yMod = EntityType.ITEM.getHeight() / 2.0F; - double x = (pos.getX() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D); - double y = (pos.getY() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D) - yMod; - double z = (pos.getZ() + 0.5F) + Mth.nextDouble(world.random, -0.25D, 0.25D); - - ItemEntity itemEntity = new ItemEntity(world, x, y, z, itemstack); - itemEntity.setDefaultPickUpDelay(); - return (Item) itemEntity.getBukkitEntity(); - } -} diff --git a/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/XEnchantment.java b/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/CustomEnchantment.java similarity index 54% rename from V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/XEnchantment.java rename to V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/CustomEnchantment.java index aad09bc..8856b8a 100644 --- a/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/XEnchantment.java +++ b/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/CustomEnchantment.java @@ -11,34 +11,45 @@ import org.bukkit.craftbukkit.v1_20_R2.CraftEquipmentSlot; import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions; -public class XEnchantment extends Enchantment { +public class CustomEnchantment extends Enchantment { - private final IEnchantment enchantment; + private final EnchantmentData enchantmentData; - public XEnchantment(@NotNull IEnchantment enchantment, @NotNull Rarity rarity) { - super(rarity, nmsCategory(enchantment), nmsSlots(enchantment)); - this.enchantment = enchantment; + private VanillaOptions vanillaOptions; + + public CustomEnchantment(@NotNull EnchantmentData enchantmentData) { + super(nmsRarity(enchantmentData), nmsCategory(enchantmentData), nmsSlots(enchantmentData)); + this.enchantmentData = enchantmentData; + + if (enchantmentData.getDistributionOptions() instanceof VanillaOptions options) { + this.vanillaOptions = options; + } } @Override public int getMinLevel() { - return this.enchantment.getStartLevel(); + return this.enchantmentData.getMinLevel(); } + @Override public int getMaxLevel() { - return this.enchantment.getMaxLevel(); + return this.enchantmentData.getMaxLevel(); } + @Override public int getMinCost(int level) { - return 1 + level * 10; // TODO + return this.enchantmentData.getMinCost(level); } + @Override public int getMaxCost(int level) { - return this.getMinCost(level) + 5; // TODO + return this.enchantmentData.getMaxCost(level); } + @Override protected boolean checkCompatibility(Enchantment other) { ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(other); if (location == null) return false; @@ -46,55 +57,54 @@ public class XEnchantment extends Enchantment { NamespacedKey key = CraftNamespacedKey.fromMinecraft(location); String id = key.getKey(); - return !this.enchantment.getConflicts().contains(id); + // Expensive probably. + //org.bukkit.enchantments.Enchantment bukkit = CraftEnchantment.minecraftToBukkit(other); + //String id = bukkit.getKey().getKey(); - //return !this.enchantment.conflictsWith(bukkit); + return !this.enchantmentData.getConflicts().contains(id); } - /*public Component getFullname(int level) { - return this.enchantment.getNameFormatted(level); - - MutableComponent var1 = Component.translatable(this.getDescriptionId()); - if (this.isCurse()) { - var1.withStyle(ChatFormatting.RED); - } else { - var1.withStyle(ChatFormatting.GRAY); - } - - if (level != 1 || this.getMaxLevel() != 1) { - var1.append(CommonComponents.SPACE).append(Component.translatable("enchantment.level." + level)); - } - - return var1; - }*/ - + @Override public boolean canEnchant(ItemStack item) { org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item); - if (this.enchantment.checkEnchantCategory(bukkitStack)) return true; - if (this.enchantment.checkItemCategory(bukkitStack)) return true; + if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true; + if (this.enchantmentData.checkItemCategory(bukkitStack)) return true; return super.canEnchant(item); } + @Override public boolean isTreasureOnly() { - return this.enchantment.isTreasure(); + return this.enchantmentData.isTreasure() || this.isCurse(); } + @Override public boolean isCurse() { - return this.enchantment.isCurse(); + return this.enchantmentData.isCurse(); } + @Override public boolean isTradeable() { - return this.enchantment.isTradeable(); + return this.vanillaOptions != null && this.vanillaOptions.isTradeable(); } + @Override public boolean isDiscoverable() { - return this.enchantment.isDiscoverable(); + return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable(); + } + + public static Rarity nmsRarity(@NotNull EnchantmentData data) { + return switch (data.getRarity()) { + case RARE -> Rarity.RARE; + case COMMON -> Rarity.COMMON; + case UNCOMMON -> Rarity.UNCOMMON; + case VERY_RARE -> Rarity.VERY_RARE; + }; } @NotNull - public static EnchantmentCategory nmsCategory(@NotNull IEnchantment enchantment) { - return switch (enchantment.getCategory()) { + public static EnchantmentCategory nmsCategory(@NotNull EnchantmentData data) { + return switch (data.getCategory()) { case WEAPON -> EnchantmentCategory.WEAPON; case TOOL -> EnchantmentCategory.DIGGER; case ARMOR -> EnchantmentCategory.ARMOR; @@ -109,12 +119,12 @@ public class XEnchantment extends Enchantment { case ARMOR_TORSO -> EnchantmentCategory.ARMOR_CHEST; case VANISHABLE -> EnchantmentCategory.VANISHABLE; case FISHING_ROD -> EnchantmentCategory.FISHING_ROD; - default -> throw new IllegalStateException("Unexpected value: " + enchantment.getCategory()); + default -> throw new IllegalStateException("Unexpected value: " + data.getCategory()); }; } - public static EquipmentSlot[] nmsSlots(@NotNull IEnchantment enchantment) { - org.bukkit.inventory.EquipmentSlot[] slots = enchantment.getSlots(); + public static EquipmentSlot[] nmsSlots(@NotNull EnchantmentData data) { + org.bukkit.inventory.EquipmentSlot[] slots = data.getSlots(); EquipmentSlot[] nmsSlots = new EquipmentSlot[slots.length]; for (int index = 0; index < nmsSlots.length; index++) { diff --git a/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/V1_20_R2.java b/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/V1_20_R2.java index e925b8a..e4642e5 100644 --- a/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/V1_20_R2.java +++ b/V1_20_R2/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R2/V1_20_R2.java @@ -11,13 +11,14 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock; @@ -27,6 +28,7 @@ import org.bukkit.craftbukkit.v1_20_R2.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R2.util.CraftMagicNumbers; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; @@ -34,11 +36,9 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.Reflex; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; -import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.nms.EnchantNMS; +import su.nightexpress.nightcore.util.Reflex; import java.util.HashSet; import java.util.IdentityHashMap; @@ -60,20 +60,13 @@ public class V1_20_R2 implements EnchantNMS { } @Override - public void registerEnchantment(@NotNull IEnchantment enchantment) { - XEnchantment xEnchantment = new XEnchantment(enchantment, net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON); - Registry.register(BuiltInRegistries.ENCHANTMENT, enchantment.getId(), xEnchantment); + public void registerEnchantment(@NotNull EnchantmentData data) { + CustomEnchantment customEnchantment = new CustomEnchantment(data); + Registry.register(BuiltInRegistries.ENCHANTMENT, data.getId(), customEnchantment); - Enchantment.registerEnchantment(new CraftEnchantment(xEnchantment)); - } - - public net.minecraft.world.item.enchantment.Enchantment.Rarity getNMSRarity(@NotNull Rarity rarity) { - return switch (rarity) { - case RARE -> net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE; - case COMMON -> net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON; - case UNCOMMON -> net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON; - case VERY_RARE -> net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE; - }; + CraftEnchantment craftEnchantment = new CraftEnchantment(customEnchantment); + Enchantment.registerEnchantment(craftEnchantment); + data.setEnchantment(craftEnchantment); } @Override @@ -91,16 +84,15 @@ public class V1_20_R2 implements EnchantNMS { handle.retrieve(CraftItemStack.asNMSCopy(item)); } + @NotNull @Override - @Nullable - public ItemStack getSpawnEgg(@NotNull LivingEntity entity) { - CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity; - net.minecraft.world.entity.LivingEntity livingEntity = craftLivingEntity.getHandle(); - - SpawnEggItem eggItem = SpawnEggItem.byId(livingEntity.getType()); - if (eggItem == null) return null; - - return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance()); + public Material getItemBlockVariant(@NotNull Material material) { + ItemStack itemStack = new ItemStack(material); + net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + if (nmsStack.getItem() instanceof BlockItem blockItem) { + return CraftMagicNumbers.getMaterial(blockItem.getBlock()); + } + return material; } @Override diff --git a/V1_20_R3/pom.xml b/V1_20_R3/pom.xml index b9d2137..f540725 100644 --- a/V1_20_R3/pom.xml +++ b/V1_20_R3/pom.xml @@ -5,7 +5,7 @@ ExcellentEnchants su.nightexpress.excellentenchants - 3.6.5 + 4.0.0 4.0.0 @@ -14,6 +14,7 @@ 17 17 + UTF-8 @@ -26,12 +27,12 @@ su.nightexpress.excellentenchants API - 3.6.5 + 4.0.0 su.nightexpress.excellentenchants NMS - 3.6.5 + 4.0.0 diff --git a/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/XEnchantment.java b/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/CustomEnchantment.java similarity index 54% rename from V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/XEnchantment.java rename to V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/CustomEnchantment.java index 7431f33..c7c0ed9 100644 --- a/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/XEnchantment.java +++ b/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/CustomEnchantment.java @@ -11,34 +11,45 @@ import org.bukkit.craftbukkit.v1_20_R3.CraftEquipmentSlot; import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack; import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey; import org.jetbrains.annotations.NotNull; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; +import su.nightexpress.excellentenchants.api.enchantment.distribution.VanillaOptions; -public class XEnchantment extends Enchantment { +public class CustomEnchantment extends Enchantment { - private final IEnchantment enchantment; + private final EnchantmentData enchantmentData; - public XEnchantment(@NotNull IEnchantment enchantment, @NotNull Rarity rarity) { - super(rarity, nmsCategory(enchantment), nmsSlots(enchantment)); - this.enchantment = enchantment; + private VanillaOptions vanillaOptions; + + public CustomEnchantment(@NotNull EnchantmentData enchantmentData) { + super(nmsRarity(enchantmentData), nmsCategory(enchantmentData), nmsSlots(enchantmentData)); + this.enchantmentData = enchantmentData; + + if (enchantmentData.getDistributionOptions() instanceof VanillaOptions options) { + this.vanillaOptions = options; + } } @Override public int getMinLevel() { - return this.enchantment.getStartLevel(); + return this.enchantmentData.getMinLevel(); } + @Override public int getMaxLevel() { - return this.enchantment.getMaxLevel(); + return this.enchantmentData.getMaxLevel(); } + @Override public int getMinCost(int level) { - return 1 + level * 10; // TODO + return this.enchantmentData.getMinCost(level); } + @Override public int getMaxCost(int level) { - return this.getMinCost(level) + 5; // TODO + return this.enchantmentData.getMaxCost(level); } + @Override protected boolean checkCompatibility(Enchantment other) { ResourceLocation location = BuiltInRegistries.ENCHANTMENT.getKey(other); if (location == null) return false; @@ -46,43 +57,54 @@ public class XEnchantment extends Enchantment { NamespacedKey key = CraftNamespacedKey.fromMinecraft(location); String id = key.getKey(); - return !this.enchantment.getConflicts().contains(id); + // Expensive probably. + //org.bukkit.enchantments.Enchantment bukkit = CraftEnchantment.minecraftToBukkit(other); + //String id = bukkit.getKey().getKey(); - //return !this.enchantment.conflictsWith(bukkit); + return !this.enchantmentData.getConflicts().contains(id); } + @Override public boolean canEnchant(ItemStack item) { org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asBukkitCopy(item); - if (this.enchantment.checkEnchantCategory(bukkitStack)) return true; - if (this.enchantment.checkItemCategory(bukkitStack)) return true; + if (this.enchantmentData.checkEnchantCategory(bukkitStack)) return true; + if (this.enchantmentData.checkItemCategory(bukkitStack)) return true; return super.canEnchant(item); - - /*if (!this.enchantment.checkEnchantCategory(CraftItemStack.asBukkitCopy(item))) { - return false; - } - return super.canEnchant(item);*/ } + @Override public boolean isTreasureOnly() { - return this.enchantment.isTreasure() || this.isCurse(); + return this.enchantmentData.isTreasure() || this.isCurse(); } + @Override public boolean isCurse() { - return this.enchantment.isCurse(); + return this.enchantmentData.isCurse(); } + @Override public boolean isTradeable() { - return this.enchantment.isTradeable(); + return this.vanillaOptions != null && this.vanillaOptions.isTradeable(); } + @Override public boolean isDiscoverable() { - return this.enchantment.isDiscoverable(); + return this.vanillaOptions != null && this.vanillaOptions.isDiscoverable(); + } + + public static Rarity nmsRarity(@NotNull EnchantmentData data) { + return switch (data.getRarity()) { + case RARE -> Rarity.RARE; + case COMMON -> Rarity.COMMON; + case UNCOMMON -> Rarity.UNCOMMON; + case VERY_RARE -> Rarity.VERY_RARE; + }; } @NotNull - public static EnchantmentCategory nmsCategory(@NotNull IEnchantment enchantment) { - return switch (enchantment.getCategory()) { + public static EnchantmentCategory nmsCategory(@NotNull EnchantmentData data) { + return switch (data.getCategory()) { case WEAPON -> EnchantmentCategory.WEAPON; case TOOL -> EnchantmentCategory.DIGGER; case ARMOR -> EnchantmentCategory.ARMOR; @@ -97,12 +119,12 @@ public class XEnchantment extends Enchantment { case ARMOR_TORSO -> EnchantmentCategory.ARMOR_CHEST; case VANISHABLE -> EnchantmentCategory.VANISHABLE; case FISHING_ROD -> EnchantmentCategory.FISHING_ROD; - default -> throw new IllegalStateException("Unexpected value: " + enchantment.getCategory()); + default -> throw new IllegalStateException("Unexpected value: " + data.getCategory()); }; } - public static EquipmentSlot[] nmsSlots(@NotNull IEnchantment enchantment) { - org.bukkit.inventory.EquipmentSlot[] slots = enchantment.getSlots(); + public static EquipmentSlot[] nmsSlots(@NotNull EnchantmentData data) { + org.bukkit.inventory.EquipmentSlot[] slots = data.getSlots(); EquipmentSlot[] nmsSlots = new EquipmentSlot[slots.length]; for (int index = 0; index < nmsSlots.length; index++) { diff --git a/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/V1_20_R3.java b/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/V1_20_R3.java index be294fb..8de9ba9 100644 --- a/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/V1_20_R3.java +++ b/V1_20_R3/src/main/java/su/nightexpress/excellentenchants/nms/v1_20_R3/V1_20_R3.java @@ -11,32 +11,34 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.projectile.FishingHook; -import net.minecraft.world.item.SpawnEggItem; +import net.minecraft.world.item.BlockItem; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock; +import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockType; +import org.bukkit.craftbukkit.v1_20_R3.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftFishHook; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_20_R3.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import su.nexmedia.engine.utils.Reflex; -import su.nightexpress.excellentenchants.api.enchantment.IEnchantment; -import su.nightexpress.excellentenchants.api.enchantment.Rarity; +import su.nightexpress.excellentenchants.api.enchantment.EnchantmentData; import su.nightexpress.excellentenchants.nms.EnchantNMS; +import su.nightexpress.nightcore.util.Reflex; import java.util.HashSet; import java.util.IdentityHashMap; @@ -46,8 +48,8 @@ public class V1_20_R3 implements EnchantNMS { @Override public void unfreezeRegistry() { - Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "l", false); - Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "m", new IdentityHashMap<>()); + Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "l", false); // MappedRegistry#frozen + Reflex.setFieldValue(BuiltInRegistries.ENCHANTMENT, "m", new IdentityHashMap<>()); // MappedRegistry#unregisteredIntrusiveHolders } @Override @@ -55,18 +57,12 @@ public class V1_20_R3 implements EnchantNMS { BuiltInRegistries.ENCHANTMENT.freeze(); } - public void registerEnchantment(@NotNull IEnchantment enchantment) { - XEnchantment xEnchantment = new XEnchantment(enchantment, getNMSRarity(Rarity.COMMON)); - Registry.register(BuiltInRegistries.ENCHANTMENT, enchantment.getId(), xEnchantment); - } + public void registerEnchantment(@NotNull EnchantmentData data) { + CustomEnchantment enchantment = new CustomEnchantment(data); + Registry.register(BuiltInRegistries.ENCHANTMENT, data.getId(), enchantment); - public net.minecraft.world.item.enchantment.Enchantment.Rarity getNMSRarity(@NotNull Rarity rarity) { - return switch (rarity) { - case RARE -> net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE; - case COMMON -> net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON; - case UNCOMMON -> net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON; - case VERY_RARE -> net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE; - }; + Enchantment bukkitEnchant = CraftEnchantment.minecraftToBukkit(enchantment); + data.setEnchantment(bukkitEnchant); } @Override @@ -84,7 +80,7 @@ public class V1_20_R3 implements EnchantNMS { handle.retrieve(CraftItemStack.asNMSCopy(item)); } - @Override + /*@Override @Nullable public ItemStack getSpawnEgg(@NotNull LivingEntity entity) { CraftLivingEntity craftLivingEntity = (CraftLivingEntity) entity; @@ -94,6 +90,17 @@ public class V1_20_R3 implements EnchantNMS { if (eggItem == null) return null; return CraftItemStack.asBukkitCopy(eggItem.getDefaultInstance()); + }*/ + + @NotNull + @Override + public Material getItemBlockVariant(@NotNull Material material) { + ItemStack itemStack = new ItemStack(material); + net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); + if (nmsStack.getItem() instanceof BlockItem blockItem) { + return CraftBlockType.minecraftToBukkit(blockItem.getBlock()); + } + return material; } @Override diff --git a/pom.xml b/pom.xml index 6b68f48..1aaa567 100644 --- a/pom.xml +++ b/pom.xml @@ -7,11 +7,10 @@ su.nightexpress.excellentenchants ExcellentEnchants pom - 3.6.5 + 4.0.0 Core NMS - V1_18_R2 V1_19_R3 V1_20_R1 V1_20_R2 @@ -20,17 +19,16 @@ - 16 - 16 + 17 + 17 UTF-8 - UTF-8 - su.nexmedia - NexEngine - 2.2.12 + su.nightexpress.nightcore + nightcore + 2.5.1