This commit is contained in:
nulli0n 2023-05-11 17:59:23 +06:00
parent 38af06c3d3
commit 9c2d0911f1
170 changed files with 2298 additions and 2182 deletions

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ExcellentEnchants</artifactId>
<groupId>su.nightexpress.excellentenchants</groupId>
<version>3.3.3</version>
<version>3.3.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -38,6 +38,23 @@
<repository>
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>lumine-repo</id>
<url>https://mvn.lumine.io/repository/maven-public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>lumine-snapshot</id>
<url>http://mvn.lumine.io/repository/maven-snapshots/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
@ -45,7 +62,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.19.3-R0.1-SNAPSHOT</version>
<version>1.19.4-R0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>su.nexmedia.playerblocktracker</groupId>
@ -55,32 +72,32 @@
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>NMS</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_17_R1</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_18_R2</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_19_R1</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_19_R2</artifactId>
<version>3.3.3</version>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_19_R3</artifactId>
<version>3.3.3</version>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_19_R2</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_19_R1</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_18_R2</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>su.nightexpress.excellentenchants</groupId>
<artifactId>V1_17_R1</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>fr.neatmonster</groupId>
@ -89,9 +106,9 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.6</version>
<groupId>io.lumine</groupId>
<artifactId>Mythic-Dist</artifactId>
<version>5.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -41,11 +41,7 @@ public class ExcellentEnchants extends NexPlugin<ExcellentEnchants> {
@Override
public void enable() {
if (!this.setNMS()) {
this.error("Could not setup internal NMS handler!");
this.getPluginManager().disablePlugin(this);
return;
}
this.setNMS();
this.tierManager = new TierManager(this);
this.tierManager.setup();
@ -67,7 +63,7 @@ public class ExcellentEnchants extends NexPlugin<ExcellentEnchants> {
PlaceholderHook.shutdown();
}
private boolean setNMS() {
private void setNMS() {
this.enchantNMS = switch (Version.CURRENT) {
case V1_17_R1 -> new V1_17_R1();
case V1_18_R2 -> new V1_18_R2();
@ -75,7 +71,6 @@ public class ExcellentEnchants extends NexPlugin<ExcellentEnchants> {
case V1_19_R2 -> new V1_19_R2();
case V1_19_R3 -> new V1_19_R3();
};
return true;
}
@Override

View File

@ -12,6 +12,11 @@ public class Placeholders extends su.nexmedia.engine.utils.Placeholders {
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_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_NAME = "%enchantment_name%";
public static final String ENCHANTMENT_NAME_FORMATTED = "%enchantment_name_formatted%";
public static final String ENCHANTMENT_DESCRIPTION = "%enchantment_description%";
@ -32,4 +37,6 @@ public class Placeholders extends su.nexmedia.engine.utils.Placeholders {
public static final String TIER_ID = "%tier_id%";
public static final String TIER_NAME = "%tier_name%";
}

View File

@ -5,7 +5,7 @@ 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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.tier.Tier;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;

View File

@ -1,8 +1,8 @@
package su.nightexpress.excellentenchants.api.enchantment.meta;
import org.bukkit.Particle;
import org.bukkit.entity.Projectile;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.particle.SimpleParticle;
import java.util.Optional;
@ -11,15 +11,10 @@ public interface Arrowed {
@NotNull Arrowed getArrowImplementation();
@NotNull
default Optional<Particle> getTrailParticle() {
default Optional<SimpleParticle> getTrailParticle() {
return this.getArrowImplementation().getTrailParticle();
}
@NotNull
default Optional<String> getTrailData() {
return this.getArrowImplementation().getTrailData();
}
default void addTrail(@NotNull Projectile projectile) {
this.getArrowImplementation().addTrail(projectile);
}

View File

@ -1,36 +0,0 @@
package su.nightexpress.excellentenchants.api.enchantment.template;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public abstract class PotionEnchant extends ExcellentEnchant implements Potioned {
private final PotionEffectType effectType;
private final boolean isPermanent;
private PotionImplementation potionImplementation;
public PotionEnchant(@NotNull ExcellentEnchants plugin, @NotNull String id, @NotNull EnchantPriority priority,
@NotNull PotionEffectType effectType, boolean isPermanent) {
super(plugin, id, priority);
this.effectType = effectType;
this.isPermanent = isPermanent;
}
@Override
public void loadConfig() {
super.loadConfig();
this.potionImplementation = PotionImplementation.create(this, this.effectType, this.isPermanent);
}
@Override
@NotNull
public Potioned getPotionImplementation() {
return this.potionImplementation;
}
}

View File

@ -4,7 +4,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.IEnchantment;
public interface BlockDropEnchant extends IEnchantment {

View File

@ -8,42 +8,26 @@ 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.lang.LangManager;
import su.nexmedia.engine.utils.CollectionsUtil;
import su.nexmedia.engine.utils.PlayerUtil;
import su.nexmedia.engine.utils.StringUtil;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Perms;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.config.Lang;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class BookCommand extends AbstractCommand<ExcellentEnchants> {
public BookCommand(@NotNull ExcellentEnchants plugin) {
super(plugin, new String[]{"book"}, Perms.COMMAND_BOOK);
}
@Override
@NotNull
public String getDescription() {
return plugin.getMessage(Lang.COMMAND_BOOK_DESC).getLocalized();
}
@Override
@NotNull
public String getUsage() {
return plugin.getMessage(Lang.COMMAND_BOOK_USAGE).getLocalized();
}
@Override
public boolean isPlayerOnly() {
return false;
this.setDescription(plugin.getMessage(Lang.COMMAND_BOOK_DESC));
this.setUsage(plugin.getMessage(Lang.COMMAND_BOOK_USAGE));
}
@Override
@ -62,32 +46,32 @@ public class BookCommand extends AbstractCommand<ExcellentEnchants> {
}
@Override
public void onExecute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args, @NotNull Map<String, String> flags) {
if (args.length != 4) {
protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) {
if (result.length() < 4) {
this.printUsage(sender);
return;
}
Player player = plugin.getServer().getPlayer(args[1]);
Player player = plugin.getServer().getPlayer(result.getArg(1));
if (player == null) {
this.errorPlayer(sender);
return;
}
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(args[2].toLowerCase()));
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(result.getArg(2).toLowerCase()));
if (enchantment == null) {
plugin.getMessage(Lang.ERROR_NO_ENCHANT).send(sender);
return;
}
int level = StringUtil.getInteger(args[3], -1, true);
int level = result.getInt(3, -1);
if (level < 1) {
level = Rnd.get(enchantment.getStartLevel(), enchantment.getMaxLevel());
}
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
EnchantManager.addEnchantment(item, enchantment, level, true);
EnchantManager.updateEnchantmentsDisplay(item);
EnchantUtils.add(item, enchantment, level, true);
EnchantUtils.updateDisplay(item);
PlayerUtil.addItem(player, item);
plugin.getMessage(Lang.COMMAND_BOOK_DONE)

View File

@ -7,38 +7,23 @@ 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.utils.StringUtil;
import su.nexmedia.engine.api.command.CommandResult;
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.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class EnchantCommand extends AbstractCommand<ExcellentEnchants> {
public EnchantCommand(@NotNull ExcellentEnchants plugin) {
super(plugin, new String[]{"enchant"}, Perms.COMMAND_ENCHANT);
}
@Override
@NotNull
public String getDescription() {
return plugin.getMessage(Lang.COMMAND_ENCHANT_DESC).getLocalized();
}
@Override
@NotNull
public String getUsage() {
return plugin.getMessage(Lang.COMMAND_ENCHANT_USAGE).getLocalized();
}
@Override
public boolean isPlayerOnly() {
return true;
this.setDescription(plugin.getMessage(Lang.COMMAND_ENCHANT_DESC));
this.setUsage(plugin.getMessage(Lang.COMMAND_ENCHANT_USAGE));
this.setPlayerOnly(true);
}
@Override
@ -54,8 +39,8 @@ public class EnchantCommand extends AbstractCommand<ExcellentEnchants> {
}
@Override
public void onExecute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args, @NotNull Map<String, String> flags) {
if (args.length != 3) {
protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) {
if (result.length() < 3) {
this.printUsage(sender);
return;
}
@ -67,23 +52,23 @@ public class EnchantCommand extends AbstractCommand<ExcellentEnchants> {
return;
}
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(args[1].toLowerCase()));
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(result.getArg(1).toLowerCase()));
if (enchantment == null) {
plugin.getMessage(Lang.ERROR_NO_ENCHANT).send(sender);
return;
}
int level = StringUtil.getInteger(args[2], -1, true);
int level = result.getInt(2, -1);
if (level < 0) {
level = Rnd.get(enchantment.getStartLevel(), enchantment.getMaxLevel());
}
if (level > 0) {
EnchantManager.addEnchantment(item, enchantment, level, true);
EnchantUtils.add(item, enchantment, level, true);
}
else EnchantManager.removeEnchantment(item, enchantment);
else EnchantUtils.remove(item, enchantment);
EnchantManager.updateEnchantmentsDisplay(item);
EnchantUtils.updateDisplay(item);
plugin.getMessage(Lang.COMMAND_ENCHANT_DONE).send(sender);
}
}

View File

@ -4,37 +4,21 @@ 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.Perms;
import su.nightexpress.excellentenchants.config.Lang;
import java.util.Map;
public class ListCommand extends AbstractCommand<ExcellentEnchants> {
public ListCommand(@NotNull ExcellentEnchants plugin) {
super(plugin, new String[]{"list"}, Perms.COMMAND_LIST);
this.setDescription(plugin.getMessage(Lang.COMMAND_LIST_DESC));
this.setPlayerOnly(true);
}
@Override
@NotNull
public String getUsage() {
return "";
}
@Override
@NotNull
public String getDescription() {
return plugin.getMessage(Lang.COMMAND_LIST_DESC).getLocalized();
}
@Override
public boolean isPlayerOnly() {
return true;
}
@Override
protected void onExecute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args, @NotNull Map<String, String> flags) {
protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) {
plugin.getEnchantManager().getEnchantsListGUI().open((Player) sender, 1);
}
}

View File

@ -6,43 +6,29 @@ 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.StringUtil;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Perms;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.config.Lang;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.tier.Tier;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class TierbookCommand extends AbstractCommand<ExcellentEnchants> {
public TierbookCommand(@NotNull ExcellentEnchants plugin) {
super(plugin, new String[]{"tierbook"}, Perms.COMMAND_TIERBOOK);
}
@Override
@NotNull
public String getDescription() {
return plugin.getMessage(Lang.COMMAND_TIER_BOOK_DESC).getLocalized();
}
@Override
@NotNull
public String getUsage() {
return plugin.getMessage(Lang.COMMAND_TIER_BOOK_USAGE).getLocalized();
}
@Override
public boolean isPlayerOnly() {
return false;
this.setDescription(plugin.getMessage(Lang.COMMAND_TIER_BOOK_DESC));
this.setUsage(plugin.getMessage(Lang.COMMAND_TIER_BOOK_USAGE));
}
@Override
@ -61,38 +47,39 @@ public class TierbookCommand extends AbstractCommand<ExcellentEnchants> {
}
@Override
public void onExecute(@NotNull CommandSender sender, @NotNull String label, @NotNull String[] args, @NotNull Map<String, String> flags) {
if (args.length != 4) {
protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) {
if (result.length() < 4) {
this.printUsage(sender);
return;
}
Player player = plugin.getServer().getPlayer(args[1]);
Player player = plugin.getServer().getPlayer(result.getArg(1));
if (player == null) {
this.errorPlayer(sender);
return;
}
Tier tier = plugin.getTierManager().getTierById(args[2].toLowerCase());
Tier tier = plugin.getTierManager().getTierById(result.getArg(2).toLowerCase());
if (tier == null) {
plugin.getMessage(Lang.COMMAND_TIER_BOOK_ERROR).send(sender);
return;
}
ExcellentEnchant enchant = Rnd.get(tier.getEnchants());
Set<ExcellentEnchant> 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 = StringUtil.getInteger(args[3], -1, true);
int level = result.getInt(3, -1);
if (level < 1) {
level = Rnd.get(enchant.getStartLevel(), enchant.getMaxLevel());
}
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
EnchantManager.addEnchantment(item, enchant, level, true);
EnchantManager.updateEnchantmentsDisplay(item);
EnchantUtils.add(item, enchant, level, true);
EnchantUtils.updateDisplay(item);
PlayerUtil.addItem(player, item);
plugin.getMessage(Lang.COMMAND_TIER_BOOK_DONE)

View File

@ -19,13 +19,17 @@ import java.util.stream.Stream;
public class Config {
public static final JOption<Long> TASKS_ARROW_TRAIL_TICKS_INTERVAL = JOption.create("Tasks.Arrow_Trail.Tick_Interval", 1L,
"Sets how often (in ticks) arrow trail particle effects will be spawned behind the arrow.");
public static final JOption<Long> TASKS_PASSIVE_POTION_EFFECTS_APPLY_INTERVAL = JOption.create("Tasks.Passive_Potion_Effects.Apply_Interval", 100L,
public static final JOption<Long> TASKS_ARROW_TRAIL_TICKS_INTERVAL = JOption.create("Tasks.Arrow_Trail.Tick_Interval",
1L,
"Sets how often (in ticks) arrow trail particle effects will be spawned behind the arrow."
);
public static final JOption<Long> TASKS_PASSIVE_POTION_EFFECTS_APPLY_INTERVAL = JOption.create("Tasks.Passive_Potion_Effects.Apply_Interval",
100L,
"Sets how often (in ticks) the plugin will apply permanent potion effects from enchanted items to an entity who wear them."
);
public static final JOption<Boolean> ENCHANTMENTS_CHARGES_ENABLED = JOption.create("Enchantments.Charges.Enabled", false,
public static final JOption<Boolean> ENCHANTMENTS_CHARGES_ENABLED = JOption.create("Enchantments.Charges.Enabled",
false,
"Enables the enchantment Charges feature.",
Placeholders.URL_WIKI + "Charges-System");

View File

@ -6,21 +6,21 @@ import su.nightexpress.excellentenchants.Placeholders;
public class Lang extends EngineLang {
public static final LangKey COMMAND_LIST_DESC = new LangKey("Command.List.Desc", "List of all custom enchantments.");
public static final LangKey COMMAND_LIST_DESC = LangKey.of("Command.List.Desc", "List of all custom enchantments.");
public static final LangKey COMMAND_ENCHANT_USAGE = new LangKey("Command.Enchant.Usage", "<enchant> <level>");
public static final LangKey COMMAND_ENCHANT_DESC = new LangKey("Command.Enchant.Desc", "Enchants the item in your hand.");
public static final LangKey COMMAND_ENCHANT_DONE = new LangKey("Command.Enchant.Done", "&aSuccessfully enchanted!");
public static final LangKey COMMAND_ENCHANT_USAGE = LangKey.of("Command.Enchant.Usage", "<enchant> <level>");
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 = LangKey.of("Command.Enchant.Done", "&aSuccessfully enchanted!");
public static final LangKey COMMAND_BOOK_USAGE = new LangKey("Command.Book.Usage", "<player> <enchant> <level>");
public static final LangKey COMMAND_BOOK_DESC = new LangKey("Command.Book.Desc", "Gives custom enchanted book.");
public static final LangKey COMMAND_BOOK_DONE = new LangKey("Command.Book.Done", "Given &6" + Placeholders.GENERIC_ENCHANT + "&7 enchanted book to &6" + Placeholders.Player.DISPLAY_NAME + "&7.");
public static final LangKey COMMAND_BOOK_USAGE = LangKey.of("Command.Book.Usage", "<player> <enchant> <level>");
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", "Given &6" + Placeholders.GENERIC_ENCHANT + "&7 enchanted book to &6" + Placeholders.Player.DISPLAY_NAME + "&7.");
public static final LangKey COMMAND_TIER_BOOK_USAGE = new LangKey("Command.TierBook.Usage", "<player> <tier> <level>");
public static final LangKey COMMAND_TIER_BOOK_DESC = new LangKey("Command.TierBook.Desc", "Gives an enchanted book.");
public static final LangKey COMMAND_TIER_BOOK_ERROR = new LangKey("Command.TierBook.Error", "&cInvalid tier!");
public static final LangKey COMMAND_TIER_BOOK_DONE = new LangKey("Command.TierBook.Done", "Given &6" + Placeholders.TIER_NAME + "&7 enchanted book to &6" + Placeholders.Player.DISPLAY_NAME + "&7.");
public static final LangKey COMMAND_TIER_BOOK_USAGE = LangKey.of("Command.TierBook.Usage", "<player> <tier> <level>");
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", "&cInvalid tier!");
public static final LangKey COMMAND_TIER_BOOK_DONE = LangKey.of("Command.TierBook.Done", "Given &6" + Placeholders.TIER_NAME + "&7 enchanted book to &6" + Placeholders.Player.DISPLAY_NAME + "&7.");
public static final LangKey ERROR_NO_ENCHANT = new LangKey("Error.NoEnchant", "&cInvalid enchantment.");
public static final LangKey ERROR_NO_ENCHANT = LangKey.of("Error.NoEnchant", "&cInvalid enchantment.");
}

View File

@ -1,45 +1,19 @@
package su.nightexpress.excellentenchants.enchantment;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.LivingEntity;
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.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.manager.AbstractManager;
import su.nexmedia.engine.utils.CollectionsUtil;
import su.nexmedia.engine.utils.EntityUtil;
import su.nexmedia.engine.utils.ItemUtil;
import su.nexmedia.engine.utils.PDCUtil;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.IEnchantment;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.config.ObtainSettings;
import su.nightexpress.excellentenchants.enchantment.listener.EnchantAnvilListener;
import su.nightexpress.excellentenchants.enchantment.listener.EnchantGenericListener;
import su.nightexpress.excellentenchants.enchantment.listener.EnchantHandlerListener;
import su.nightexpress.excellentenchants.enchantment.menu.EnchantmentsListMenu;
import su.nightexpress.excellentenchants.enchantment.task.ArrowTrailsTask;
import su.nightexpress.excellentenchants.enchantment.task.PotionEffectsTask;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.tier.Tier;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;
public class EnchantManager extends AbstractManager<ExcellentEnchants> {
public static final String DIR_ENCHANTS = "/enchants/";
private EnchantmentsListMenu enchantmentsListMenu;
private ArrowTrailsTask arrowTrailsTask;
@ -51,7 +25,7 @@ public class EnchantManager extends AbstractManager<ExcellentEnchants> {
@Override
protected void onLoad() {
EnchantRegister.setup();
EnchantRegistry.setup();
this.enchantmentsListMenu = new EnchantmentsListMenu(this.plugin);
this.addListener(new EnchantHandlerListener(this));
@ -79,320 +53,11 @@ public class EnchantManager extends AbstractManager<ExcellentEnchants> {
this.potionEffectsTask.stop();
this.potionEffectsTask = null;
}
EnchantRegister.shutdown();
EnchantRegistry.shutdown();
}
@NotNull
public EnchantmentsListMenu getEnchantsListGUI() {
return enchantmentsListMenu;
}
public static boolean isEnchantable(@NotNull ItemStack item) {
if (item.getType().isAir()) return false;
return item.getType() == Material.ENCHANTED_BOOK || Stream.of(EnchantmentTarget.values()).anyMatch(target -> target.includes(item));
}
@NotNull
public static Map<Enchantment, Integer> getEnchantsToPopulate(@NotNull ItemStack item, @NotNull ObtainType obtainType) {
return getEnchantsToPopulate(item, obtainType, new HashMap<>(), (enchant) -> enchant.generateLevel(obtainType));
}
@NotNull
public static Map<Enchantment, Integer> getEnchantsToPopulate(@NotNull ItemStack item, @NotNull ObtainType obtainType,
@NotNull Map<Enchantment, Integer> enchantsPrepared,
@NotNull Function<ExcellentEnchant, Integer> levelFunc) {
Map<Enchantment, Integer> enchantsToAdd = new HashMap<>(enchantsPrepared);
ObtainSettings settings = Config.getObtainSettings(obtainType).orElse(null);
if (settings == null || !Rnd.chance(settings.getEnchantsCustomGenerationChance())) return enchantsToAdd;
int enchMax = settings.getEnchantsTotalMax();
int enchRoll = Rnd.get(settings.getEnchantsCustomMin(), settings.getEnchantsCustomMax());
// Класс для исключения неудачных попыток.
EnchantPopulator populator = new EnchantPopulator(obtainType, item);
// Добавляем сколько можем, пока нужное количество не будет добавлено или не закончатся чары и/или тиры.
while (!populator.isEmpty() && enchRoll > 0) {
// Достигнут максимум чар (любых) для итема, заканчиваем.
if (enchantsToAdd.size() >= enchMax) break;
Tier tier = populator.getTierByChance();
if (tier == null) break; // Нет тира?
ExcellentEnchant enchant = populator.getEnchantByChance(tier);
// В тире нет подходящих чар (вообще) для итема, исключаем и идем дальше.
if (enchant == null) {
populator.getEnchants().remove(tier);
continue;
}
// Среди уже добавленных чар есть конфликты с тем, что нашли.
// Исключаем, идем дальше.
if (enchantsToAdd.keySet().stream().anyMatch(has -> has.conflictsWith(enchant) || enchant.conflictsWith(has))) {
populator.getEnchants(tier).remove(enchant);
continue;
}
// Не получилось сгенерировать подходящий уровень.
// Исключаем, идем дальше.
int level = levelFunc.apply(enchant);
if (level < enchant.getStartLevel()) {
populator.getEnchants(tier).remove(enchant);
continue;
}
// Добавляем чар, засчитываем попытку.
populator.getEnchants(tier).remove(enchant);
enchantsToAdd.put(enchant, level);
enchRoll--;
}
return enchantsToAdd;
}
public static boolean populateEnchantments(@NotNull ItemStack item, @NotNull ObtainType obtainType) {
int enchantsHad = EnchantManager.getEnchantmentsAmount(item);
EnchantManager.getEnchantsToPopulate(item, obtainType).forEach((enchantment, level) -> {
EnchantManager.addEnchantment(item, enchantment, level, false);
});
EnchantManager.updateEnchantmentsDisplay(item);
return EnchantManager.getEnchantmentsAmount(item) != enchantsHad;
}
public static boolean addEnchantment(@NotNull ItemStack item, @NotNull Enchantment enchantment, int level, boolean force) {
if (!force && !enchantment.canEnchantItem(item)) return false;
EnchantManager.removeEnchantment(item, enchantment);
ItemMeta meta = item.getItemMeta();
if (meta == null) return false;
if (meta instanceof EnchantmentStorageMeta storageMeta) {
if (!storageMeta.addStoredEnchant(enchantment, level, true)) return false;
}
else {
if (!meta.addEnchant(enchantment, level, true)) return false;
}
item.setItemMeta(meta);
return true;
}
public static void removeEnchantment(@NotNull ItemStack item, @NotNull Enchantment enchantment) {
ItemMeta meta = item.getItemMeta();
if (meta instanceof EnchantmentStorageMeta storageMeta) {
storageMeta.removeStoredEnchant(enchantment);
}
else {
meta.removeEnchant(enchantment);
}
item.setItemMeta(meta);
}
public static final NamespacedKey KEY_LORE_SIZE = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "lore_size");
public static boolean updateEnchantmentsDisplay(@NotNull ItemStack item) {
if (Config.ENCHANTMENTS_DISPLAY_MODE.get() != 1) return false;
if (!isEnchantable(item)) {
PDCUtil.remove(item, KEY_LORE_SIZE);
return false;
}
Map<ExcellentEnchant, Integer> enchants = EnchantManager.getExcellentEnchantments(item);
int sizeHas = PDCUtil.getInt(item, KEY_LORE_SIZE).orElse(0);
int sizeReal = enchants.size();
ItemMeta meta = item.getItemMeta();
if (meta == null) return false;
List<String> lore = meta.getLore() == null ? new ArrayList<>() : meta.getLore();
for (int index = 0; index < sizeHas && !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 (Config.ENCHANTMENTS_DESCRIPTION_ENABLED.get()) {
enchants.forEach((enchant, level) -> {
lore.addAll(0, enchant.formatDescription(level));
});
sizeReal += enchants.keySet().stream().map(ExcellentEnchant::getDescription).mapToInt(List::size).sum();
}
enchants.forEach((enchant, level) -> {
lore.add(0, enchant.getNameFormatted(level, getEnchantmentCharges(meta, enchant)));
});
}
else sizeReal = 0;
meta.setLore(lore);
if (sizeReal > 0) {
PDCUtil.set(meta, KEY_LORE_SIZE, sizeReal);
}
item.setItemMeta(meta);
return true;
}
@NotNull
public static Map<Enchantment, Integer> getEnchantments(@NotNull ItemStack item) {
ItemMeta meta = item.getItemMeta();
return meta == null ? Collections.emptyMap() : getEnchantments(meta);
}
@NotNull
public static Map<Enchantment, Integer> getEnchantments(@NotNull ItemMeta meta) {
return (meta instanceof EnchantmentStorageMeta meta2) ? meta2.getStoredEnchants() : meta.getEnchants();
}
public static int getEnchantmentsAmount(@NotNull ItemStack item) {
return EnchantManager.getEnchantments(item).size();
}
public static boolean hasEnchantment(@NotNull ItemStack item, @NotNull Enchantment enchantment) {
return EnchantManager.getEnchantmentLevel(item, enchantment) > 0;
}
public static int getEnchantmentLevel(@NotNull ItemStack item, @NotNull Enchantment enchant) {
return EnchantManager.getEnchantments(item).getOrDefault(enchant, 0);
}
public static int getEnchantmentCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
return enchant.isChargesEnabled() ? PDCUtil.getInt(item, enchant.getChargesKey()).orElse(-0) : -1;
}
public static int getEnchantmentCharges(@NotNull ItemMeta meta, @NotNull ExcellentEnchant enchant) {
return enchant.isChargesEnabled() ? PDCUtil.getInt(meta, enchant.getChargesKey()).orElse(0) : -1;
}
public static boolean isEnchantmentOutOfCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
return enchant.isChargesEnabled() && getEnchantmentCharges(item, enchant) == 0;
}
public static boolean isEnchantmentFullOfCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return true;
int level = getEnchantmentLevel(item, enchant);
int max = enchant.getChargesMax(level);
return EnchantManager.getEnchantmentCharges(item, enchant) == max;
}
public static void consumeEnchantmentCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return;
int level = getEnchantmentLevel(item, enchant);
int has = getEnchantmentCharges(item, enchant);
int use = enchant.getChargesConsumeAmount(level);
EnchantManager.setEnchantmentCharges(item, enchant, has - use);
}
public static void restoreEnchantmentCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return;
int level = getEnchantmentLevel(item, enchant);
int max = enchant.getChargesMax(level);
EnchantManager.setEnchantmentCharges(item, enchant, max);
}
public static void rechargeEnchantmentCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return;
int level = getEnchantmentLevel(item, enchant);
int recharge = enchant.getChargesRechargeAmount(level);
int has = getEnchantmentCharges(item, enchant);
EnchantManager.setEnchantmentCharges(item, enchant, has + recharge);
}
public static void setEnchantmentCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int charges) {
if (!enchant.isChargesEnabled()) return;
int level = getEnchantmentLevel(item, enchant);
int max = enchant.getChargesMax(level);
PDCUtil.set(item, enchant.getChargesKey(), Math.max(0, Math.min(charges, max)));
}
public static int getExcellentEnchantmentsAmount(@NotNull ItemStack item) {
return EnchantManager.getExcellentEnchantments(item).size();
}
@NotNull
public static Map<ExcellentEnchant, Integer> getExcellentEnchantments(@NotNull ItemStack item) {
return getExcellentEnchantments(EnchantManager.getEnchantments(item));
}
@NotNull
public static Map<ExcellentEnchant, Integer> getExcellentEnchantments(@NotNull ItemMeta meta) {
return getExcellentEnchantments(EnchantManager.getEnchantments(meta));
}
@NotNull
private static Map<ExcellentEnchant, Integer> getExcellentEnchantments(@NotNull Map<Enchantment, Integer> enchants) {
Map<ExcellentEnchant, Integer> map = new HashMap<>();
enchants.forEach((enchantment, level) -> {
ExcellentEnchant excellent = EnchantRegister.get(enchantment.getKey());
if (excellent != null) {
map.put(excellent, level);
}
});
return map;
}
@NotNull
public static <T extends IEnchantment> Map<T, Integer> getExcellentEnchantments(@NotNull ItemStack item, @NotNull Class<T> clazz) {
Map<T, Integer> map = new HashMap<>();
EnchantManager.getEnchantments(item).forEach((enchantment, level) -> {
ExcellentEnchant excellent = EnchantRegister.get(enchantment.getKey());
if (excellent == null || !clazz.isAssignableFrom(excellent.getClass())) return;
map.put(clazz.cast(excellent), level);
});
return CollectionsUtil.sort(map, Comparator.comparing(p -> p.getKey().getPriority(), Comparator.reverseOrder()));
}
@NotNull
public static Map<EquipmentSlot, ItemStack> getEquipmentEnchanted(@NotNull LivingEntity entity) {
Map<EquipmentSlot, ItemStack> equipment = EntityUtil.getEquippedItems(entity);
equipment.entrySet().removeIf(entry -> {
ItemStack item = entry.getValue();
EquipmentSlot slot = entry.getKey();
if (item == null || item.getType().isAir() || item.getType() == Material.ENCHANTED_BOOK) return true;
if ((slot == EquipmentSlot.HAND || slot == EquipmentSlot.OFF_HAND) && ItemUtil.isArmor(item)) return true;
return !item.hasItemMeta();
});
return equipment;
}
@NotNull
public static Map<ItemStack, Map<ExcellentEnchant, Integer>> getEquippedEnchants(@NotNull LivingEntity entity) {
Map<ItemStack, Map<ExcellentEnchant, Integer>> map = new HashMap<>();
EnchantManager.getEquipmentEnchanted(entity).values().forEach(item -> {
map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(EnchantManager.getExcellentEnchantments(item));
});
return map;
}
@NotNull
public static <T extends IEnchantment> Map<ItemStack, Map<T, Integer>> getEquippedEnchants(@NotNull LivingEntity entity, @NotNull Class<T> clazz) {
Map<ItemStack, Map<T, Integer>> map = new HashMap<>();
EnchantManager.getEquipmentEnchanted(entity).values().forEach(item -> {
map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(EnchantManager.getExcellentEnchantments(item, clazz));
});
return map;
}
public static void updateEquippedEnchantEffects(@NotNull LivingEntity entity) {
EnchantManager.getEquippedEnchants(entity, PassiveEnchant.class).forEach((item, enchants) -> {
enchants.forEach((enchant, level) -> {
if (enchant instanceof Potioned potioned) {
if (enchant.isOutOfCharges(item)) return;
if (enchant.onTrigger(entity, item, level)) {
enchant.consumeCharges(item);
}
}
});
});
}
}

View File

@ -5,8 +5,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.tier.Tier;
import java.util.HashMap;
@ -24,8 +25,12 @@ public class EnchantPopulator {
public EnchantPopulator(@NotNull ObtainType obtainType, @NotNull ItemStack item) {
this.obtainType = obtainType;
this.item = item;
this.enchants = ExcellentEnchantsAPI.getTierManager().getTiers().stream()
.collect(Collectors.toMap(k -> k, v -> v.getEnchants(obtainType, item), (prev, add) -> add, HashMap::new));
this.enchants = new HashMap<>();
ExcellentEnchantsAPI.getTierManager().getTiers().forEach(tier -> {
Set<ExcellentEnchant> enchants = EnchantRegistry.getOfTier(tier);
this.enchants.put(tier, EnchantUtils.populateFilter(enchants, obtainType, item));
});
}
public boolean isEmpty() {
@ -67,15 +72,14 @@ public class EnchantPopulator {
@Nullable
public Tier getTierByChance() {
Map<Tier, Double> map = this.getEnchants().keySet().stream()
.collect(Collectors.toMap(k -> k, v -> v.getChance(this.getObtainType())));
return Rnd.get(map);
if (this.getEnchants().keySet().isEmpty()) return null;
return ExcellentEnchantsAPI.getTierManager().getTierByChance(this.getObtainType());
}
@Nullable
public ExcellentEnchant getEnchantByChance(@NotNull Tier tier) {
Map<ExcellentEnchant, Double> map = this.getEnchants(tier).stream()
.collect(Collectors.toMap(k -> k, v -> v.getObtainChance(this.getObtainType())));
return map.isEmpty() ? null : Rnd.get(map);
return map.isEmpty() ? null : Rnd.getByWeight(map);
}
}

View File

@ -7,22 +7,23 @@ import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.api.manager.ICleanable;
import su.nexmedia.engine.utils.Reflex;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.tool.*;
import su.nightexpress.excellentenchants.enchantment.impl.universal.EnchantCurseOfFragility;
import su.nightexpress.excellentenchants.enchantment.impl.weapon.*;
import su.nightexpress.excellentenchants.tier.Tier;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
public class EnchantRegister {
public class EnchantRegistry {
private static final ExcellentEnchants PLUGIN;
public static final Map<NamespacedKey, ExcellentEnchant> ENCHANT_REGISTRY;
public static final Map<NamespacedKey, ExcellentEnchant> REGISTRY_MAP;
public static final EnchantBlastMining BLAST_MINING;
public static final EnchantCurseOfBreaking CURSE_OF_BREAKING;
@ -92,8 +93,7 @@ public class EnchantRegister {
static {
PLUGIN = ExcellentEnchants.getPlugin(ExcellentEnchants.class);
PLUGIN.getConfigManager().extractResources("/enchants/");
ENCHANT_REGISTRY = new HashMap<>();
REGISTRY_MAP = new HashMap<>();
// Tool enchants
BLAST_MINING = init(EnchantBlastMining.class, EnchantBlastMining.ID);
@ -170,17 +170,17 @@ public class EnchantRegister {
public static void setup() {
// Prevent to register enchantments during the runtime.
if (ExcellentEnchants.isLoaded) {
ENCHANT_REGISTRY.values().forEach(ExcellentEnchant::loadConfig);
REGISTRY_MAP.values().forEach(ExcellentEnchant::loadConfig);
return;
}
Reflex.setFieldValue(Enchantment.class, "acceptingNew", true);
for (Field field : EnchantRegister.class.getFields()) {
for (Field field : EnchantRegistry.class.getFields()) {
if (!ExcellentEnchant.class.isAssignableFrom(field.getType())) continue;
try {
ExcellentEnchant enchant = (ExcellentEnchant) field.get(null);
EnchantRegister.register(enchant);
EnchantRegistry.register(enchant);
}
catch (Exception e) {
e.printStackTrace();
@ -188,7 +188,7 @@ public class EnchantRegister {
}
Enchantment.stopAcceptingRegistrations();
PLUGIN.info("Enchantments Registered: " + ENCHANT_REGISTRY.size());
PLUGIN.info("Enchantments Registered: " + REGISTRY_MAP.size());
ExcellentEnchants.isLoaded = true;
}
@ -201,7 +201,7 @@ public class EnchantRegister {
if (byKey == null || byName == null) return;
for (ExcellentEnchant enchant : ENCHANT_REGISTRY.values()) {
for (ExcellentEnchant enchant : REGISTRY_MAP.values()) {
if (enchant instanceof ICleanable cleanable) {
cleanable.clear();
}
@ -210,15 +210,10 @@ public class EnchantRegister {
byName.remove(enchant.getName());
enchant.unregisterListeners();
}
ENCHANT_REGISTRY.clear();
REGISTRY_MAP.clear();
PLUGIN.info("All enchants are unregistered.");
}
@Nullable
public static ExcellentEnchant get(@NotNull NamespacedKey key) {
return ENCHANT_REGISTRY.get(key);
}
@Nullable
private static <T extends ExcellentEnchant> T init(@NotNull Class<T> clazz, @NotNull String id) {
if (Config.ENCHANTMENTS_DISABLED.get().contains(id)) return null;
@ -236,10 +231,27 @@ public class EnchantRegister {
if (enchant == null) return;
Enchantment.registerEnchantment(enchant);
ENCHANT_REGISTRY.put(enchant.getKey(), enchant);
REGISTRY_MAP.put(enchant.getKey(), enchant);
enchant.loadConfig();
enchant.getConfig().saveChanges();
enchant.registerListeners();
PLUGIN.info("Registered enchantment: " + enchant.getId());
}
@Nullable
public static ExcellentEnchant get(@NotNull NamespacedKey key) {
return REGISTRY_MAP.get(key);
}
@NotNull
public static Collection<ExcellentEnchant> getRegistered() {
return REGISTRY_MAP.values();
}
@NotNull
public static Set<ExcellentEnchant> getOfTier(@NotNull Tier tier) {
return getRegistered().stream().filter(enchant -> enchant.getTier() == tier)
.collect(Collectors.toCollection(HashSet::new));
}
}

View File

@ -0,0 +1,296 @@
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.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.tier.Tier;
import su.nightexpress.excellentenchants.tier.TierManager;
import java.util.*;
public class EnchantDefaults {
private final Map<ObtainType, Double> obtainChance;
private final Map<ObtainType, int[]> obtainLevelCap;
private String displayName;
private Tier tier;
private List<String> description;
private boolean isTreasure;
private int levelMin;
private int levelMax;
private EnchantScaler levelByEnchantCost;
private EnchantScaler anvilMergeCost;
private Set<String> 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.setTreasure(false);
this.setLevelMin(1);
this.setLevelMax(3);
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.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));
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.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<String> description) {
this.description = Colorizer.apply(description);
}
@NotNull
public List<String> getDescription() {
return description;
}
public boolean isTreasure() {
return isTreasure;
}
public void setTreasure(boolean treasure) {
isTreasure = treasure;
}
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;
}
@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<ObtainType, Double> getObtainChance() {
return obtainChance;
}
@NotNull
public Map<ObtainType, int[]> getObtainLevelCap() {
return obtainLevelCap;
}
public void setConflicts(@NotNull String... conflicts) {
this.setConflicts(new HashSet<>(Arrays.asList(conflicts)));
}
public void setConflicts(@NotNull Set<String> conflicts) {
this.conflicts = conflicts;
}
@NotNull
public Set<String> 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;
}
}

View File

@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.utils.Scaler;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import java.util.ArrayList;
import java.util.Arrays;

View File

@ -1,4 +1,4 @@
package su.nightexpress.excellentenchants.api.enchantment;
package su.nightexpress.excellentenchants.enchantment.impl;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@ -8,24 +8,23 @@ 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.JOption;
import su.nexmedia.engine.api.config.JYML;
import su.nexmedia.engine.api.manager.IListener;
import su.nexmedia.engine.lang.LangManager;
import su.nexmedia.engine.utils.*;
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.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantDefaults;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.tier.Tier;
import java.util.*;
@ -38,119 +37,22 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
protected final JYML cfg;
protected final String id;
protected final EnchantPriority priority;
protected String displayName;
protected Tier tier;
protected List<String> description;
protected boolean isTreasure;
protected int levelMin;
protected int levelMax;
protected Scaler levelByEnchantCost;
protected Scaler anvilMergeCost;
protected Map<ObtainType, Double> obtainChance;
protected Set<String> conflicts;
protected Map<ObtainType, int[]> obtainLevelCap;
protected boolean hasVisualEffects;
protected boolean chargesEnabled;
protected boolean chargesCustomFuel;
protected EnchantScaler chargesMax;
protected EnchantScaler chargesConsumeAmount;
protected EnchantScaler chargesRechargeAmount;
protected ItemStack chargesFuel;
protected final EnchantDefaults defaults;
protected final NamespacedKey chargesKey;
public ExcellentEnchant(@NotNull ExcellentEnchants plugin, @NotNull String id, @NotNull EnchantPriority priority) {
super(NamespacedKey.minecraft(id.toLowerCase()));
this.plugin = plugin;
this.id = this.getKey().getKey();
this.cfg = JYML.loadOrExtract(plugin, "/enchants/" + id + ".yml");
this.cfg = new JYML(plugin.getDataFolder() + "/enchants/", id + ".yml");
this.priority = priority;
this.conflicts = new HashSet<>();
this.chargesKey = new NamespacedKey(plugin, this.getId() + ".charges");
this.defaults = new EnchantDefaults(this);
}
public void loadConfig() {
this.cfg.reload();
this.displayName = JOption.create("Name", StringUtil.capitalizeFully(this.getId().replace("_", " ")),
"Enchantment display name. It will be shown in item lore.")
.mapReader(Colorizer::apply).read(cfg);
this.tier = plugin.getTierManager().getTierById(JOption.create("Tier", Placeholders.DEFAULT,
"Enchantment tier. Must be a valid tier identifier from the 'tiers.yml'.").read(cfg));
if (this.tier == null) {
this.tier = Tier.DEFAULT;
}
this.tier.getEnchants().add(this);
this.description = JOption.create("Description", new ArrayList<>(),
"Enchantment description. It will be shown in item lore under enchantment name.",
"You can use 'Enchantment' placeholders: " + Placeholders.URL_PLACEHOLDERS)
.mapReader(Colorizer::apply).read(cfg);
this.isTreasure = JOption.create("Is_Treasure", false,
"Sets whether this enchantment is a treasure enchantment.",
"Treasure enchantments can only be received via looting, trading, or fishing.").read(cfg);
this.levelMin = Math.max(1, JOption.create("Level.Min", 1,
"Sets the minimal (start) enchantment level. Can not be less than 1.").read(cfg));
this.levelMax = JOption.create("Level.Max", 3,
"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.levelByEnchantCost = EnchantScaler.read(this, 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.anvilMergeCost = EnchantScaler.read(this, "Anvil.Merge_Cost", Placeholders.ENCHANTMENT_LEVEL,
"Sets how much XP levels will be added to the anvil cost when combining custom enchantments.");
this.obtainChance = new HashMap<>();
this.obtainLevelCap = new HashMap<>();
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.obtainChance.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.obtainLevelCap.put(obtainType, new int[]{levelMin, levelMax});
}
this.conflicts = JOption.create("Conflicts", new HashSet<>(),
"A list of conflicting enchantment names.",
"Conflicting enchantments can not be combined on anvils and obtained together on the same item.").read(cfg);
this.hasVisualEffects = JOption.create("Settings.Visual_Effects", true,
"Enables/Disables enchantment visual effects, such as particles.").read(cfg);
if (Config.ENCHANTMENTS_CHARGES_ENABLED.get()) {
this.chargesEnabled = JOption.create("Settings.Charges.Enabled", false,
"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.chargesCustomFuel = JOption.create("Settings.Charges.Custom_Fuel", false,
"When 'true' uses different (non-default) fuel item (from the 'Fuel_Item' setting) to recharge.").read(cfg);
this.chargesMax = EnchantScaler.read(this, "Settings.Charges.Maximum", "100",
"Maximum amount of charges for the enchantment.");
this.chargesConsumeAmount = EnchantScaler.read(this, "Settings.Charges.Consume_Amount", "1",
"How many charges will be consumed when enchantment is triggered?");
this.chargesRechargeAmount = EnchantScaler.read(this, "Settings.Charges.Recharge_Amount", "25",
"How many charges will be restored when using 'Fuel Item' in anvil?");
this.chargesFuel = 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);
}
this.getDefaults().load(this);
}
@NotNull
@ -181,13 +83,13 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
str = str.replace(Placeholders.ENCHANTMENT_DESCRIPTION, String.join("\n", this.getDescription()));
if (this instanceof Chanced chanced) {
str = str.replace(ChanceImplementation.PLACEHOLDER_CHANCE, NumberUtil.format(chanced.getTriggerChance(level)));
str = str.replace(Placeholders.ENCHANTMENT_CHANCE, NumberUtil.format(chanced.getTriggerChance(level)));
}
if (this instanceof Potioned potioned) {
str = str
.replace(PotionImplementation.PLACEHOLDER_POTION_LEVEL, NumberUtil.toRoman(potioned.getEffectAmplifier(level)))
.replace(PotionImplementation.PLACEHOLDER_POTION_DURATION, NumberUtil.format((double) potioned.getEffectDuration(level) / 20D))
.replace(PotionImplementation.PLACEHOLDER_POTION_TYPE, LangManager.getPotionType(potioned.getEffectType()));
.replace(Placeholders.ENCHANTMENT_POTION_LEVEL, NumberUtil.toRoman(potioned.getEffectAmplifier(level)))
.replace(Placeholders.ENCHANTMENT_POTION_DURATION, NumberUtil.format((double) potioned.getEffectDuration(level) / 20D))
.replace(Placeholders.ENCHANTMENT_POTION_TYPE, LangManager.getPotionType(potioned.getEffectType()));
}
return str;
};
@ -228,6 +130,11 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
return priority;
}
@NotNull
public EnchantDefaults getDefaults() {
return defaults;
}
@NotNull
@Override
public String getName() {
@ -236,7 +143,7 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
@NotNull
public String getDisplayName() {
return this.displayName;
return this.getDefaults().getDisplayName();
}
@NotNull
@ -259,12 +166,12 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
@NotNull
public List<String> getDescription() {
return this.description;
return this.getDefaults().getDescription();
}
@NotNull
public List<String> getDescription(int level) {
List<String> description = new ArrayList<>(this.description);
List<String> description = new ArrayList<>(this.getDescription());
description.replaceAll(this.replacePlaceholders(level));
return description;
}
@ -278,26 +185,26 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
@NotNull
public Set<String> getConflicts() {
return conflicts;
return this.getDefaults().getConflicts();
}
@NotNull
public Tier getTier() {
return this.tier;
return this.getDefaults().getTier();
}
@Override
public int getMaxLevel() {
return this.levelMax;
return this.getDefaults().getLevelMax();
}
@Override
public int getStartLevel() {
return this.levelMin;
return this.getDefaults().getLevelMin();
}
public int getLevelByEnchantCost(int expLevel) {
int get = this.levelByEnchantCost.getValues().entrySet().stream()
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);
@ -305,15 +212,15 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
}
public double getObtainChance(@NotNull ObtainType obtainType) {
return this.obtainChance.getOrDefault(obtainType, 0D);
return this.getDefaults().getObtainChance().getOrDefault(obtainType, 0D);
}
public int getObtainLevelMin(@NotNull ObtainType obtainType) {
return this.obtainLevelCap.getOrDefault(obtainType, new int[]{-1, -1})[0];
return this.getDefaults().getObtainLevelCap().getOrDefault(obtainType, new int[]{-1, -1})[0];
}
public int getObtainLevelMax(@NotNull ObtainType obtainType) {
return this.obtainLevelCap.getOrDefault(obtainType, new int[]{-1, -1})[1];
return this.getDefaults().getObtainLevelCap().getOrDefault(obtainType, new int[]{-1, -1})[1];
}
public int fineLevel(int level, @NotNull ObtainType obtainType) {
@ -341,19 +248,19 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
}
public int getAnvilMergeCost(int level) {
return (int) this.anvilMergeCost.getValue(level);
return (int) this.getDefaults().getAnvilMergeCost().getValue(level);
}
@Override
public final boolean conflictsWith(@NotNull Enchantment enchantment) {
return this.conflicts.contains(enchantment.getKey().getKey());
return this.getConflicts().contains(enchantment.getKey().getKey());
}
@Override
public final boolean canEnchantItem(@Nullable ItemStack item) {
if (item == null || item.getType().isAir()) return false;
if (EnchantManager.getEnchantments(item).keySet().stream().anyMatch(e -> e.conflictsWith(this) || this.conflictsWith(e))) return false;
if (EnchantManager.getEnchantmentLevel(item, this) <= 0 && EnchantManager.getExcellentEnchantmentsAmount(item) >= Config.ENCHANTMENTS_ITEM_CUSTOM_MAX.get()) {
if (EnchantUtils.getAll(item).keySet().stream().anyMatch(e -> e.conflictsWith(this) || this.conflictsWith(e))) return false;
if (EnchantUtils.getLevel(item, this) <= 0 && EnchantUtils.getExcellentAmount(item) >= Config.ENCHANTMENTS_ITEM_CUSTOM_MAX.get()) {
return false;
}
if (item.getType() == Material.BOOK || item.getType() == Material.ENCHANTED_BOOK) {
@ -369,36 +276,36 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
@Override
public final boolean isTreasure() {
return this.isTreasure;
return this.getDefaults().isTreasure();
}
public boolean hasVisualEffects() {
return this.hasVisualEffects;
return this.getDefaults().isVisualEffects();
}
public boolean isChargesEnabled() {
return Config.ENCHANTMENTS_CHARGES_ENABLED.get() && this.chargesEnabled;
return Config.ENCHANTMENTS_CHARGES_ENABLED.get() && this.getDefaults().isChargesEnabled();
}
public boolean isChargesCustomFuel() {
return chargesCustomFuel;
return this.getDefaults().isChargesCustomFuel();
}
public int getChargesMax(int level) {
return this.isChargesEnabled() ? (int) this.chargesMax.getValue(level) : 0;
return this.isChargesEnabled() ? (int) this.getDefaults().getChargesMax().getValue(level) : 0;
}
public int getChargesConsumeAmount(int level) {
return this.isChargesEnabled() ? (int) this.chargesConsumeAmount.getValue(level) : 0;
return this.isChargesEnabled() ? (int) this.getDefaults().getChargesConsumeAmount().getValue(level) : 0;
}
public int getChargesRechargeAmount(int level) {
return this.isChargesEnabled() ? (int) this.chargesRechargeAmount.getValue(level) : 0;
return this.isChargesEnabled() ? (int) this.getDefaults().getChargesRechargeAmount().getValue(level) : 0;
}
@NotNull
public ItemStack getChargesFuel() {
ItemStack fuelHas = this.chargesFuel;
ItemStack fuelHas = this.getDefaults().getChargesFuel();
if (!this.isChargesCustomFuel() || fuelHas == null || fuelHas.getType().isAir()) {
return Config.ENCHANTMENTS_CHARGES_FUEL_ITEM.get();
}
@ -416,22 +323,22 @@ public abstract class ExcellentEnchant extends Enchantment implements IEnchantme
@Override
public boolean isOutOfCharges(@NotNull ItemStack item) {
return EnchantManager.isEnchantmentOutOfCharges(item, this);
return EnchantUtils.isOutOfCharges(item, this);
}
@Override
public boolean isFullOfCharges(@NotNull ItemStack item) {
return EnchantManager.isEnchantmentFullOfCharges(item, this);
return EnchantUtils.isFullOfCharges(item, this);
}
@Override
public int getCharges(@NotNull ItemStack item) {
return EnchantManager.getEnchantmentCharges(item, this);
return EnchantUtils.getCharges(item, this);
}
@Override
public void consumeCharges(@NotNull ItemStack item) {
EnchantManager.consumeEnchantmentCharges(item, this);
EnchantManager.updateEnchantmentsDisplay(item);
EnchantUtils.consumeCharges(item, this);
EnchantUtils.updateDisplay(item);
}
}

View File

@ -6,16 +6,36 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantAquaman extends PotionEnchant implements PassiveEnchant {
public class EnchantAquaman extends ExcellentEnchant implements Potioned, PassiveEnchant {
public static final String ID = "aquaman";
private PotionImplementation potionImplementation;
public EnchantAquaman(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.WATER_BREATHING, true);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.potionImplementation = PotionImplementation.create(this, PotionEffectType.WATER_BREATHING, true);
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override

View File

@ -6,16 +6,36 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantBunnyHop extends PotionEnchant implements PassiveEnchant {
public class EnchantBunnyHop extends ExcellentEnchant implements Potioned, PassiveEnchant {
public static final String ID = "bunny_hop";
private PotionImplementation potionImplementation;
public EnchantBunnyHop(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.JUMP, true);
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0.1);
this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect.");
}
@Override
public void loadConfig() {
super.loadConfig();
this.potionImplementation = PotionImplementation.create(this, PotionEffectType.JUMP, true);
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override

View File

@ -7,26 +7,39 @@ 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.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantColdSteel extends PotionEnchant implements Chanced, CombatEnchant {
public class EnchantColdSteel extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant {
public static final String ID = "cold_steel";
private ChanceImplementation chanceImplementation;
private PotionImplementation potionImplementation;
public EnchantColdSteel(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.SLOW_DIGGING, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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);
}
@NotNull
@ -35,6 +48,12 @@ public class EnchantColdSteel extends PotionEnchant implements Chanced, CombatEn
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override
@NotNull
public EnchantmentTarget getItemTarget() {

View File

@ -11,10 +11,10 @@ import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.Set;
import java.util.function.UnaryOperator;
@ -36,6 +36,9 @@ public class EnchantElementalProtection extends ExcellentEnchant {
public EnchantElementalProtection(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Reduces Poison, Magic, Wither, Lightning, Freeze damage by " + PLACEHOLDER_PROTECTION_AMOUNT + ".");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(0.2);
}
@Override
@ -51,7 +54,8 @@ public class EnchantElementalProtection extends ExcellentEnchant {
public void loadConfig() {
super.loadConfig();
this.protectionAmount = EnchantScaler.read(this, "Settings.Protection.Amount", "0.05 * " + Placeholders.ENCHANTMENT_LEVEL,
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);
@ -85,8 +89,8 @@ public class EnchantElementalProtection extends ExcellentEnchant {
if (!this.isAvailableToUse(entity)) return;
double protectionAmount = 0D;
for (ItemStack armor : EnchantManager.getEquipmentEnchanted(entity).values()) {
int level = EnchantManager.getEnchantmentLevel(armor, this);
for (ItemStack armor : EnchantUtils.getEnchantedEquipment(entity).values()) {
int level = EnchantUtils.getLevel(armor, this);
if (level <= 0) continue;
protectionAmount += this.getProtectionAmount(level);

View File

@ -8,10 +8,10 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
@ -27,6 +27,9 @@ public class EnchantFireShield extends ExcellentEnchant implements Chanced, Comb
public EnchantFireShield(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
@ -41,8 +44,10 @@ public class EnchantFireShield extends ExcellentEnchant implements Chanced, Comb
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.fireDuration = EnchantScaler.read(this, "Settings.Fire.Duration", "2.5 * " + Placeholders.ENCHANTMENT_LEVEL,
this.chanceImplementation = ChanceImplementation.create(this,
Placeholders.ENCHANTMENT_LEVEL + " * 15.0");
this.fireDuration = EnchantScaler.read(this, "Settings.Fire.Duration",
"2.5 * " + Placeholders.ENCHANTMENT_LEVEL,
"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.");

View File

@ -5,6 +5,7 @@ import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@ -17,14 +18,14 @@ import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.manager.ICleanable;
import su.nexmedia.engine.api.task.AbstractTask;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.api.server.AbstractTask;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -42,6 +43,10 @@ public class EnchantFlameWalker extends ExcellentEnchant implements ICleanable {
public EnchantFlameWalker(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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();
@ -91,7 +96,7 @@ public class EnchantFlameWalker extends ExcellentEnchant implements ICleanable {
ItemStack boots = player.getInventory().getBoots();
if (boots == null || boots.getType().isAir()) return;
int level = EnchantManager.getEnchantmentLevel(boots, this);
int level = EnchantUtils.getLevel(boots, this);
if (level <= 0) return;
Block bTo = to.getBlock().getRelative(BlockFace.DOWN);
@ -124,7 +129,7 @@ public class EnchantFlameWalker extends ExcellentEnchant implements ICleanable {
ItemStack boots = equipment.getBoots();
if (boots == null || boots.getType().isAir()) return;
int level = EnchantManager.getEnchantmentLevel(boots, this);
int level = EnchantUtils.getLevel(boots, this);
if (level <= 0) return;
e.setCancelled(true);
@ -146,7 +151,8 @@ public class EnchantFlameWalker extends ExcellentEnchant implements ICleanable {
long time = BLOCKS_TO_DESTROY.get(block);
if (now >= time) {
block.setType(Material.LAVA);
EffectUtil.playEffect(block.getLocation(), Particle.BLOCK_CRACK, Material.MAGMA_BLOCK.name(), 0.5, 0.7, 0.5, 0.03, 50);
SimpleParticle.of(Particle.BLOCK_CRACK, Material.MAGMA_BLOCK)
.play(block.getLocation(), 0.5, 0.7, 0.5, 0.03, 30);
return true;
}
return false;

View File

@ -7,26 +7,38 @@ 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.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantHardened extends PotionEnchant implements Chanced, CombatEnchant {
public class EnchantHardened extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant {
public static final String ID = "hardened";
private ChanceImplementation chanceImplementation;
private PotionImplementation potionImplementation;
public EnchantHardened(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.DAMAGE_RESISTANCE, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"30.0 * " + Placeholders.ENCHANTMENT_LEVEL);
this.potionImplementation = PotionImplementation.create(this, PotionEffectType.DAMAGE_RESISTANCE, false,
"3.0" + Placeholders.ENCHANTMENT_LEVEL,
Placeholders.ENCHANTMENT_LEVEL);
}
@NotNull
@ -35,6 +47,12 @@ public class EnchantHardened extends PotionEnchant implements Chanced, CombatEnc
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override
@NotNull
public EnchantmentTarget getItemTarget() {

View File

@ -8,28 +8,38 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantIceShield extends PotionEnchant implements Chanced, CombatEnchant {
public class EnchantIceShield extends ExcellentEnchant implements Chanced, Potioned, CombatEnchant {
public static final String ID = "ice_shield";
private ChanceImplementation chanceImplementation;
private PotionImplementation potionImplementation;
public EnchantIceShield(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.SLOW, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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);
}
@NotNull
@ -44,6 +54,12 @@ public class EnchantIceShield extends PotionEnchant implements Chanced, CombatEn
return this.chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override
public boolean onAttack(@NotNull EntityDamageByEntityEvent e, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) {
return false;
@ -58,7 +74,8 @@ public class EnchantIceShield extends PotionEnchant implements Chanced, CombatEn
damager.setFreezeTicks(damager.getMaxFreezeTicks());
if (this.hasVisualEffects()) {
EffectUtil.playEffect(damager.getEyeLocation(), Particle.BLOCK_CRACK, Material.ICE.name(), 0.25, 0.25, 0.25, 0.1f, 15);
SimpleParticle.of(Particle.BLOCK_CRACK, Material.ICE)
.play(damager.getEyeLocation(), 0.25, 0.1, 20);
}
return true;
}

View File

@ -6,16 +6,36 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantNightVision extends PotionEnchant implements PassiveEnchant {
public class EnchantNightVision extends ExcellentEnchant implements Potioned, PassiveEnchant {
public static final String ID = "night_vision";
private PotionImplementation potionImplementation;
public EnchantNightVision(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.NIGHT_VISION, true);
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0.7);
}
@Override
public void loadConfig() {
super.loadConfig();
this.potionImplementation = PotionImplementation.create(this, PotionEffectType.NIGHT_VISION, true);
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override

View File

@ -8,18 +8,19 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.api.manager.ICleanable;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.EntityUtil;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
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.task.AbstractEnchantmentTask;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.function.UnaryOperator;
@ -42,13 +43,16 @@ public class EnchantRegrowth extends ExcellentEnchant implements Chanced, Passiv
public EnchantRegrowth(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Restores " + PLACEHOLDER_HEAL_AMOUNT + " hearts every " + PLACEHOLDER_HEAL_INTERVAL + "s.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(0.7);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5");
this.healInterval = JOption.create("Settings.Heal.Interval", 100,
"How often (in ticks) enchantment will have effect? 1 second = 20 ticks.").read(cfg);
this.healMinHealth = EnchantScaler.read(this, "Settings.Heal.Min_Health", "0.5",
@ -127,7 +131,7 @@ public class EnchantRegrowth extends ExcellentEnchant implements Chanced, Passiv
entity.setHealth(amount);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(entity.getEyeLocation(), Particle.HEART, "", 0.3, 0.3, 0.3, 0.1, 5);
SimpleParticle.of(Particle.HEART).play(entity.getEyeLocation(), 0.25, 0.1, 5);
}
return true;
}
@ -141,7 +145,7 @@ public class EnchantRegrowth extends ExcellentEnchant implements Chanced, Passiv
@Override
public void action() {
for (LivingEntity entity : this.getEntities()) {
EnchantManager.getEquippedEnchants(entity, EnchantRegrowth.class).forEach((item, enchants) -> {
EnchantUtils.getEquipped(entity, EnchantRegrowth.class).forEach((item, enchants) -> {
enchants.forEach((enchant, level) -> {
if (enchant.isOutOfCharges(item)) return;
if (enchant.onTrigger(entity, item, level)) {

View File

@ -10,12 +10,12 @@ import su.nexmedia.engine.api.manager.ICleanable;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.task.AbstractEnchantmentTask;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.function.UnaryOperator;
@ -35,6 +35,9 @@ public class EnchantSaturation extends ExcellentEnchant implements PassiveEnchan
public EnchantSaturation(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Restores " + PLACEHOLDER_SATURATION_AMOUNT + " food points every " + PLACEHOLDER_SATURATION_INTERVAL + "s.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0.5);
}
@Override
@ -112,7 +115,7 @@ public class EnchantSaturation extends ExcellentEnchant implements PassiveEnchan
@Override
public void action() {
for (LivingEntity entity : this.getEntities()) {
EnchantManager.getEquippedEnchants(entity, EnchantSaturation.class).forEach((item, enchants) -> {
EnchantUtils.getEquipped(entity, EnchantSaturation.class).forEach((item, enchants) -> {
enchants.forEach((enchant, level) -> {
if (enchant.isOutOfCharges(item)) return;
if (enchant.onTrigger(entity, item, level)) {

View File

@ -13,10 +13,10 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
@ -34,13 +34,18 @@ public class EnchantSelfDestruction extends ExcellentEnchant implements Chanced,
public EnchantSelfDestruction(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("%enchantment_trigger_chance%% chance to create an explosion on death.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0.3);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.explosionSize = EnchantScaler.read(this, "Settings.Explosion.Size", "1.0" + Placeholders.ENCHANTMENT_LEVEL,
this.chanceImplementation = ChanceImplementation.create(this,
"20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 10");
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.");
}

View File

@ -6,16 +6,36 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantSonic extends PotionEnchant implements PassiveEnchant {
public class EnchantSonic extends ExcellentEnchant implements Potioned, PassiveEnchant {
public static final String ID = "sonic";
private PotionImplementation potionImplementation;
public EnchantSonic(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.SPEED, true);
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0.3);
}
@Override
public void loadConfig() {
super.loadConfig();
this.potionImplementation = PotionImplementation.create(this, PotionEffectType.SPEED, true);
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override

View File

@ -1,5 +1,6 @@
package su.nightexpress.excellentenchants.enchantment.impl.bow;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Projectile;
@ -12,10 +13,10 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
@ -31,13 +32,27 @@ public class EnchantBomber extends ExcellentEnchant implements Chanced, BowEncha
public EnchantBomber(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGHEST);
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,
EnchantHover.ID,
Enchantment.ARROW_FIRE.getKey().getKey(),
Enchantment.ARROW_KNOCKBACK.getKey().getKey(),
Enchantment.ARROW_DAMAGE.getKey().getKey()
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.fuseTicks = EnchantScaler.read(this, "Settings.Fuse_Ticks", "100 - " + Placeholders.ENCHANTMENT_LEVEL + " * 10",
this.chanceImplementation = ChanceImplementation.create(this,
"5.0 * " + Placeholders.ENCHANTMENT_LEVEL);
this.fuseTicks = EnchantScaler.read(this, "Settings.Fuse_Ticks",
"100 - " + Placeholders.ENCHANTMENT_LEVEL + " * 10",
"Sets fuse ticks (before it will explode) for the launched TNT.");
}

View File

@ -1,5 +1,6 @@
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;
@ -11,31 +12,48 @@ 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.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
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 PotionEnchant implements Chanced, Arrowed, BowEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.CONFUSION, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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, EnchantHover.ID,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.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
@ -50,6 +68,12 @@ public class EnchantConfusingArrows extends PotionEnchant implements Chanced, Ar
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {

View File

@ -16,14 +16,15 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
@ -45,16 +46,28 @@ public class EnchantDragonfireArrows extends ExcellentEnchant implements Chanced
public EnchantDragonfireArrows(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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, EnchantHover.ID,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.fireDuration = EnchantScaler.read(this, "Settings.Fire.Duration", "100 * " + Placeholders.ENCHANTMENT_LEVEL,
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.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,
this.fireRadius = EnchantScaler.read(this, "Settings.Fire.Radius",
"2.0 + " + Placeholders.ENCHANTMENT_LEVEL,
"Sets the dragonfire cloud effect radius.");
}

View File

@ -1,5 +1,6 @@
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;
@ -15,16 +16,17 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.LocationUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantElectrifiedArrows extends ExcellentEnchant implements Chanced, Arrowed, BowEnchant {
@ -37,13 +39,23 @@ public class EnchantElectrifiedArrows extends ExcellentEnchant implements Chance
public EnchantElectrifiedArrows(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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, EnchantHover.ID,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantDragonfireArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.of(Particle.FIREWORKS_SPARK));
this.chanceImplementation = ChanceImplementation.create(this,
"10.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5");
}
@NotNull
@ -79,8 +91,9 @@ public class EnchantElectrifiedArrows extends ExcellentEnchant implements Chance
Block block = e.getHitBlock();
block.getWorld().strikeLightning(block.getLocation()).setMetadata(META_NO_ITEM_DAMAGE, new FixedMetadataValue(plugin, true));
if (this.hasVisualEffects()) {
EffectUtil.playEffect(LocationUtil.getCenter(block.getLocation()), Particle.BLOCK_CRACK, block.getType().name(), 1D, 1D, 1D, 0.05, 150);
EffectUtil.playEffect(LocationUtil.getCenter(block.getLocation()), Particle.FIREWORKS_SPARK, "", 1D, 1D, 1D, 0.05, 150);
Location center = LocationUtil.getCenter(block.getLocation());
SimpleParticle.of(Particle.BLOCK_CRACK, block.getType()).play(center, 1, 0.05, 120);
SimpleParticle.of(Particle.FIREWORKS_SPARK).play(center, 1, 0.05, 120);
}
return true;
}

View File

@ -1,5 +1,6 @@
package su.nightexpress.excellentenchants.enchantment.impl.bow;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.EnderPearl;
import org.bukkit.entity.LivingEntity;
@ -10,10 +11,10 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
public class EnchantEnderBow extends ExcellentEnchant implements BowEnchant, Chanced {
@ -24,12 +25,25 @@ public class EnchantEnderBow extends ExcellentEnchant implements BowEnchant, Cha
public EnchantEnderBow(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGHEST);
this.getDefaults().setDescription("Shoots ender pearls instead of arrows.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(1.0);
this.getDefaults().setConflicts(
EnchantBomber.ID, EnchantGhast.ID,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID,
EnchantHover.ID,
Enchantment.ARROW_FIRE.getKey().getKey(),
Enchantment.ARROW_KNOCKBACK.getKey().getKey(),
Enchantment.ARROW_DAMAGE.getKey().getKey()
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this, "100");
}
@NotNull

View File

@ -1,5 +1,6 @@
package su.nightexpress.excellentenchants.enchantment.impl.bow;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.*;
@ -13,14 +14,15 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ArrowImplementation;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
@ -44,20 +46,31 @@ public class EnchantExplosiveArrows extends ExcellentEnchant implements Chanced,
public EnchantExplosiveArrows(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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, EnchantHover.ID,
EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.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,
this.explosionSize = EnchantScaler.read(this, "Settings.Explosion.Size",
"2.0 + " + Placeholders.ENCHANTMENT_LEVEL,
"Sets the explosion size. The more size - the bigger explosion.");
}

View File

@ -14,13 +14,13 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
public class EnchantGhast extends ExcellentEnchant implements BowEnchant, Chanced {
@ -32,12 +32,25 @@ public class EnchantGhast extends ExcellentEnchant implements BowEnchant, Chance
public EnchantGhast(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGHEST);
this.getDefaults().setDescription("Shoots fireballs instead of arrows.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0.3);
this.getDefaults().setConflicts(
EnchantEnderBow.ID, EnchantBomber.ID,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID,
EnchantHover.ID,
Enchantment.ARROW_FIRE.getKey().getKey(),
Enchantment.ARROW_KNOCKBACK.getKey().getKey(),
Enchantment.ARROW_DAMAGE.getKey().getKey()
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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,
@ -74,7 +87,7 @@ public class EnchantGhast extends ExcellentEnchant implements BowEnchant, Chance
// Shoot small fireballs for the Multishot enchantment,
// as large ones has a slow speed and punches each other on shoot.
if (EnchantManager.hasEnchantment(bow, Enchantment.MULTISHOT)) {
if (EnchantUtils.contains(bow, Enchantment.MULTISHOT)) {
fireball = shooter.launchProjectile(SmallFireball.class);
fireball.setVelocity(projectile.getVelocity().normalize().multiply(0.5f));
}

View File

@ -1,5 +1,6 @@
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;
@ -11,31 +12,48 @@ 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.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
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 PotionEnchant implements Chanced, Arrowed, BowEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.LEVITATION, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.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
@ -50,6 +68,12 @@ public class EnchantHover extends PotionEnchant implements Chanced, Arrowed, Bow
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {

View File

@ -1,5 +1,6 @@
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;
@ -11,31 +12,49 @@ 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.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
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 PotionEnchant implements Chanced, Arrowed, BowEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.POISON, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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, EnchantHover.ID,
EnchantExplosiveArrows.ID, EnchantConfusingArrows.ID,
EnchantWitheredArrows.ID, EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.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
@ -50,6 +69,12 @@ public class EnchantPoisonedArrows extends PotionEnchant implements Chanced, Arr
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {

View File

@ -1,5 +1,6 @@
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;
@ -11,31 +12,49 @@ 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.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.BowEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
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 PotionEnchant implements Chanced, Arrowed, BowEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.WITHER, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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, EnchantHover.ID,
EnchantExplosiveArrows.ID, EnchantPoisonedArrows.ID, EnchantConfusingArrows.ID,
EnchantElectrifiedArrows.ID, EnchantDragonfireArrows.ID
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.arrowImplementation = ArrowImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this);
this.arrowImplementation = ArrowImplementation.create(this, SimpleParticle.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
@ -50,6 +69,12 @@ public class EnchantWitheredArrows extends PotionEnchant implements Chanced, Arr
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {

View File

@ -0,0 +1,5 @@
package su.nightexpress.excellentenchants.enchantment.impl.fishing;
public class SpeedFishingEnchant {
}

View File

@ -7,9 +7,10 @@ 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.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.PDCUtil;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed;
import su.nightexpress.excellentenchants.enchantment.task.ArrowTrailsTask;
@ -20,29 +21,30 @@ public final class ArrowImplementation implements Arrowed {
private final ExcellentEnchant enchant;
private final NamespacedKey projectileKey;
private final Particle trailParticle;
private final String trailData;
private final SimpleParticle trailParticle;
private ArrowImplementation(@NotNull ExcellentEnchant enchant,
@Nullable Particle trailParticle, @Nullable String trailData) {
private ArrowImplementation(@NotNull ExcellentEnchant enchant, @Nullable SimpleParticle trailParticle) {
this.enchant = enchant;
this.projectileKey = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "arrow.enchant_id");
this.trailParticle = trailParticle;
this.trailData = trailData;
}
@NotNull
public static ArrowImplementation create(@NotNull ExcellentEnchant enchant) {
JYML cfg = enchant.getConfig();
Particle trailParticle = JOption.create("Settings.Arrow.Trail_Effect.Name", Particle.class, Particle.REDSTONE,
"Particle name for the arrow trail effect.",
"https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Particle.html").read(cfg);
String trailData = JOption.create("Settings.Arrow.Trail_Effect.Data", "",
"Particle data for the particle effect.",
"This is required for certain particles only.").read(cfg);
return create(enchant, SimpleParticle.of(Particle.REDSTONE));
}
return new ArrowImplementation(enchant, trailParticle, trailData);
@NotNull
public static ArrowImplementation create(@NotNull ExcellentEnchant enchant, @NotNull SimpleParticle particle) {
JYML cfg = enchant.getConfig();
SimpleParticle effect = new JOption<>("Settings.Arrow.Trail_Effect",
(cfg1, path, def) -> SimpleParticle.read(cfg1, path),
particle,
"Sets particle effect for the arrow trail of this enchantment."
).setWriter((cfg1, path, particle1) -> SimpleParticle.write(particle1, cfg1, path)).read(cfg);
return new ArrowImplementation(enchant, effect);
}
@Override
@ -56,24 +58,17 @@ public final class ArrowImplementation implements Arrowed {
if (!this.enchant.hasVisualEffects()) return;
if (this.getTrailParticle().isEmpty()) return;
Particle particle = this.getTrailParticle().get();
String data = this.getTrailData().orElse("");
ArrowTrailsTask.add(projectile, particle, data);
this.getTrailParticle().ifPresent(particle -> {
ArrowTrailsTask.add(projectile, particle);
});
}
@NotNull
@Override
public Optional<Particle> getTrailParticle() {
public Optional<SimpleParticle> getTrailParticle() {
return trailParticle == null ? Optional.empty() : Optional.of(trailParticle);
}
@NotNull
@Override
public Optional<String> getTrailData() {
return trailData == null ? Optional.empty() : Optional.of(trailData);
}
@NotNull
public NamespacedKey getProjectileKey() {
return projectileKey;

View File

@ -2,14 +2,12 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
public final class ChanceImplementation implements Chanced {
public static final String PLACEHOLDER_CHANCE = "%enchantment_trigger_chance%";
//private final ExcellentEnchant enchant;
private final EnchantScaler triggerChance;
@ -20,7 +18,12 @@ public final class ChanceImplementation implements Chanced {
@NotNull
public static ChanceImplementation create(@NotNull ExcellentEnchant enchant) {
return new ChanceImplementation(enchant, EnchantScaler.read(enchant, "Settings.Trigger_Chance", "100",
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."));
}

View File

@ -6,30 +6,26 @@ import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.utils.Scaler;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
public final class PotionImplementation implements Potioned {
public static final String PLACEHOLDER_POTION_LEVEL = "%enchantment_potion_level%";
public static final String PLACEHOLDER_POTION_DURATION = "%enchantment_potion_duration%";
public static final String PLACEHOLDER_POTION_TYPE = "%enchantment_potion_type%";
//private final ExcellentEnchant enchant;
private final PotionEffectType effectType;
private final Scaler duration;
private final Scaler amplifier;
private final boolean isPermanent;
private PotionImplementation(@NotNull ExcellentEnchant enchant, @NotNull PotionEffectType effectType, 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 = EnchantScaler.read(enchant, "Settings.Potion_Effect.Duration", "5.0 * " + Placeholders.ENCHANTMENT_LEVEL,
"Potion effect duration (in seconds). This setting is useless for 'permanent' effects.");
this.amplifier = EnchantScaler.read(enchant, "Settings.Potion_Effect.Level", Placeholders.ENCHANTMENT_LEVEL,
"Potion effect level.");
this.duration = duration;
this.amplifier = amplifier;
this.isPermanent = isPermanent;
}
@ -40,7 +36,20 @@ public final class PotionImplementation implements Potioned {
}
public static PotionImplementation create(@NotNull ExcellentEnchant enchant, @NotNull PotionEffectType type, boolean isPermanent) {
return new PotionImplementation(enchant, type, 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

View File

@ -16,14 +16,14 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.EnchantRegister;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
@ -45,15 +45,22 @@ public class EnchantBlastMining extends ExcellentEnchant implements Chanced, Blo
public EnchantBlastMining(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to mine blocks by explosion.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(1.0);
this.getDefaults().setConflicts(EnchantVeinminer.ID, EnchantTunnel.ID);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.explosionPower = EnchantScaler.read(this, "Settings.Explosion.Power", "3.0 + (" + Placeholders.ENCHANTMENT_LEVEL + " - 1.0 * 0.25)",
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)",
"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 = EnchantScaler.read(this, "Settings.Min_Block_Strength",
"1.5 - " + Placeholders.ENCHANTMENT_LEVEL + " / 10",
"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.");
@ -101,8 +108,8 @@ public class EnchantBlastMining extends ExcellentEnchant implements Chanced, Blo
public boolean onBreak(@NotNull BlockBreakEvent e, @NotNull Player player, @NotNull ItemStack item, int level) {
if (!this.isAvailableToUse(player)) return false;
if (EnchantRegister.VEINMINER != null && EnchantManager.hasEnchantment(item, EnchantRegister.VEINMINER)) return false;
if (EnchantRegister.TUNNEL != null && EnchantManager.hasEnchantment(item, EnchantRegister.TUNNEL)) return false;
if (EnchantRegistry.VEINMINER != null && EnchantUtils.contains(item, EnchantRegistry.VEINMINER)) return false;
if (EnchantRegistry.TUNNEL != null && EnchantUtils.contains(item, EnchantRegistry.TUNNEL)) return false;
Block block = e.getBlock();
if (block.hasMetadata(META_EXPLOSION_MINED)) return false;

View File

@ -10,12 +10,12 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.function.UnaryOperator;
@ -29,13 +29,18 @@ public class EnchantCurseOfBreaking extends ExcellentEnchant implements Chanced
public EnchantCurseOfBreaking(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to consume extra " + PLACEHOLDER_DURABILITY_AMOUNT + " durability points.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0D);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.durabilityAmount = EnchantScaler.read(this, "Settings.Durability_Amount", Placeholders.ENCHANTMENT_LEVEL,
this.chanceImplementation = ChanceImplementation.create(this,
"10.0 * " + Placeholders.ENCHANTMENT_LEVEL);
this.durabilityAmount = EnchantScaler.read(this, "Settings.Durability_Amount",
Placeholders.ENCHANTMENT_LEVEL,
"Amount of durability points to be taken from the item.");
}
@ -73,7 +78,7 @@ public class EnchantCurseOfBreaking extends ExcellentEnchant implements Chanced
if (!this.isAvailableToUse(player)) return;
ItemStack item = e.getItem();
int level = EnchantManager.getEnchantmentLevel(item, this);
int level = EnchantUtils.getLevel(item, this);
if (level < 1) return;
if (!this.checkTriggerChance(level)) return;

View File

@ -1,5 +1,6 @@
package su.nightexpress.excellentenchants.enchantment.impl.tool;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@ -9,11 +10,12 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
@ -26,12 +28,20 @@ public class EnchantCurseOfMisfortune extends ExcellentEnchant implements Chance
public EnchantCurseOfMisfortune(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.LOWEST);
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(
Enchantment.LOOT_BONUS_BLOCKS.getKey().getKey(),
Enchantment.LOOT_BONUS_MOBS.getKey().getKey()
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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);
}

View File

@ -18,19 +18,19 @@ import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.Colorizer;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.utils.LocationUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
public class EnchantDivineTouch extends ExcellentEnchant implements Chanced, BlockBreakEnchant, BlockDropEnchant {
@ -42,13 +42,19 @@ public class EnchantDivineTouch extends ExcellentEnchant implements Chanced, Blo
public EnchantDivineTouch(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to mine spawner.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(1.0);
this.getDefaults().setConflicts(EnchantSmelter.ID);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.spawnerName = JOption.create("Settings.Spawner_Item.Name", "&aMob Spawner &7(" + Placeholders.GENERIC_TYPE + ")",
this.chanceImplementation = ChanceImplementation.create(this,
"15.0 * " + Placeholders.ENCHANTMENT_LEVEL);
this.spawnerName = JOption.create("Settings.Spawner_Item.Name",
"&aMob Spawner &7(" + Placeholders.GENERIC_TYPE + ")",
"Spawner item display name.",
"Placeholder '" + Placeholders.GENERIC_TYPE + "' for the mob type.")
.mapReader(Colorizer::apply).read(cfg);
@ -99,7 +105,7 @@ public class EnchantDivineTouch extends ExcellentEnchant implements Chanced, Blo
Location location = LocationUtil.getCenter(block.getLocation());
if (this.hasVisualEffects()) {
EffectUtil.playEffect(location, Particle.VILLAGER_HAPPY, "", 0.3f, 0.3f, 0.3f, 0.15f, 30);
SimpleParticle.of(Particle.VILLAGER_HAPPY).play(location, 0.3, 0.15, 30);
}
block.removeMetadata(META_HANDLE, this.plugin);
return true;

View File

@ -6,16 +6,36 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantHaste extends PotionEnchant implements PassiveEnchant {
public class EnchantHaste extends ExcellentEnchant implements Potioned, PassiveEnchant {
public static final String ID = "haste";
private PotionImplementation potionImplementation;
public EnchantHaste(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM, PotionEffectType.FAST_DIGGING, true);
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Grants permanent " + Placeholders.ENCHANTMENT_POTION_TYPE + " " + Placeholders.ENCHANTMENT_POTION_LEVEL + " effect.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0.3);
}
@Override
public void loadConfig() {
super.loadConfig();
this.potionImplementation = PotionImplementation.create(this, PotionEffectType.FAST_DIGGING, true);
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@Override

View File

@ -8,10 +8,10 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
@ -28,13 +28,18 @@ public class EnchantLuckyMiner extends ExcellentEnchant implements Chanced, Bloc
public EnchantLuckyMiner(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.expModifier = EnchantScaler.read(this, "Settings.Exp_Modifier", "1.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.5",
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.");
}

View File

@ -17,11 +17,11 @@ import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.utils.MessageUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.InteractEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
@ -43,12 +43,15 @@ public class EnchantReplanter extends ExcellentEnchant implements Chanced, Inter
public EnchantReplanter(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGH);
this.getDefaults().setDescription("Automatically replant crops on right click and when harvest.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0.3);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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,

View File

@ -25,10 +25,10 @@ import su.nexmedia.engine.utils.ItemUtil;
import su.nexmedia.engine.utils.PDCUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import java.util.ArrayList;
@ -48,6 +48,10 @@ public class EnchantSilkChest extends ExcellentEnchant implements BlockDropEncha
public EnchantSilkChest(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGH);
this.getDefaults().setDescription("Drop chests and saves all its content.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0.5);
this.keyChest = new NamespacedKey(plugin, ID + ".item");
this.keyItems = new TreeMap<>();
for (int pos = 0; pos < 27; pos++) {

View File

@ -6,26 +6,28 @@ import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.block.Container;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.LocationUtil;
import su.nexmedia.engine.utils.MessageUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class EnchantSmelter extends ExcellentEnchant implements Chanced, BlockDropEnchant {
@ -37,37 +39,39 @@ public class EnchantSmelter extends ExcellentEnchant implements Chanced, BlockDr
public EnchantSmelter(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to smelt a block/ore.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(0.3);
this.getDefaults().setConflicts(
EnchantDivineTouch.ID,
Enchantment.SILK_TOUCH.getKey().getKey()
);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 10");
this.sound = JOption.create("Settings.Sound", Sound.class, Sound.BLOCK_LAVA_EXTINGUISH,
"Sound to play on smelting.",
"https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html").read(cfg);
this.smeltingTable = new HashMap<>();
for (String sFrom : cfg.getSection("Settings.Smelting_Table")) {
Material mFrom = Material.getMaterial(sFrom.toUpperCase());
if (mFrom == null) {
plugin.error("[Smelter] Invalid source material '" + sFrom + "' !");
continue;
}
String sTo = cfg.getString("Settings.Smelting_Table." + sFrom, "");
Material mTo = Material.getMaterial(sTo.toUpperCase());
if (mTo == null) {
plugin.error("[Smelter] Invalid result material '" + sTo + "' !");
continue;
}
this.smeltingTable.put(mFrom, mTo);
}
this.cfg.setComments("Settings.Smelting_Table",
this.smeltingTable = JOption.forMap("Settings.Smelting_Table",
str -> Material.getMaterial(str.toLowerCase()),
(cfg, path, id) -> Material.getMaterial(cfg.getString(path + "." + id, "").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");
"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.smeltingTable.keySet().removeIf(Objects::isNull);
this.smeltingTable.values().removeIf(Objects::isNull);
}
@NotNull
@ -104,7 +108,7 @@ public class EnchantSmelter extends ExcellentEnchant implements Chanced, BlockDr
if (this.hasVisualEffects()) {
Location location = LocationUtil.getCenter(block.getLocation(), true);
MessageUtil.sound(location, this.sound);
EffectUtil.playEffect(location, Particle.FLAME, "", 0.2f, 0.2f, 0.2f, 0.05f, 30);
SimpleParticle.of(Particle.FLAME).play(location, 0.25, 0.05, 20);
}
return true;
}

View File

@ -8,11 +8,11 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockDropEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
@ -28,12 +28,15 @@ public class EnchantTelekinesis extends ExcellentEnchant implements Chanced, Blo
public EnchantTelekinesis(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.LOWEST);
this.getDefaults().setDescription("Moves all blocks loot directly to your inventory.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0.75);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this, "100");
}
@NotNull

View File

@ -1,30 +1,36 @@
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.Player;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.manager.ICleanable;
import su.nexmedia.engine.utils.random.Rnd;
import su.nexmedia.playerblocktracker.PlayerBlockTracker;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
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.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import java.util.*;
import java.util.function.Predicate;
public class EnchantTreasures extends ExcellentEnchant implements Chanced, BlockDropEnchant, ICleanable {
public class EnchantTreasures extends ExcellentEnchant implements Chanced, BlockBreakEnchant, BlockDropEnchant, ICleanable {
public static final String ID = "treasures";
private static final String META = "wasted";
private Map<Material, Map<Material, Double>> treasures;
private ChanceImplementation chanceImplementation;
@ -33,19 +39,42 @@ public class EnchantTreasures extends ExcellentEnchant implements Chanced, Block
public EnchantTreasures(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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(plugin);
PlayerBlockTracker.BLOCK_FILTERS.add(this.blockTracker = (block) -> {
return !this.getTreasures(block.getType()).isEmpty();
return this.treasures.containsKey(block.getType());
});
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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());
@ -77,6 +106,7 @@ public class EnchantTreasures extends ExcellentEnchant implements Chanced, Block
@Override
public void clear() {
PlayerBlockTracker.BLOCK_FILTERS.remove(this.blockTracker);
PlayerBlockTracker.shutdown();
}
@NotNull
@ -97,11 +127,22 @@ public class EnchantTreasures extends ExcellentEnchant implements Chanced, Block
return EnchantmentTarget.TOOL;
}
@Override
public boolean onBreak(@NotNull BlockBreakEvent e, @NotNull Player player, @NotNull ItemStack item, int level) {
if (PlayerBlockTracker.isTracked(e.getBlock())) {
e.getBlock().setMetadata(META, new FixedMetadataValue(plugin, true));
}
return false;
}
@Override
public boolean onDrop(@NotNull BlockDropItemEvent e, @NotNull EnchantDropContainer dropContainer, @NotNull Player player, @NotNull ItemStack item, int level) {
Block block = e.getBlockState().getBlock();
if (block.hasMetadata(META)) {
block.removeMetadata(META, plugin);
return false;
}
if (!this.isAvailableToUse(player)) return false;
if (PlayerBlockTracker.isTracked(block)) return false;
if (!this.checkTriggerChance(level)) return false;
dropContainer.getDrop().addAll(this.getTreasures(e.getBlockState().getType()));

View File

@ -1,7 +1,6 @@
package su.nightexpress.excellentenchants.enchantment.impl.tool;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.enchantments.EnchantmentTarget;
@ -11,16 +10,15 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.utils.LocationUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.EnchantRegister;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook;
import java.util.HashSet;
import java.util.Set;
@ -42,6 +40,10 @@ public class EnchantTunnel extends ExcellentEnchant implements BlockBreakEnchant
public EnchantTunnel(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGH);
this.getDefaults().setDescription("Mines multiple blocks at once in a certain shape.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(1.0);
this.getDefaults().setConflicts(EnchantVeinminer.ID, EnchantBlastMining.ID);
}
@Override
@ -68,8 +70,8 @@ public class EnchantTunnel extends ExcellentEnchant implements BlockBreakEnchant
Block block = e.getBlock();
if (!this.isAvailableToUse(player)) return false;
if (this.disableOnSneak && player.isSneaking()) return false;
if (EnchantRegister.VEINMINER != null && EnchantManager.hasEnchantment(item, EnchantRegister.VEINMINER)) return false;
if (EnchantRegister.BLAST_MINING != null && EnchantManager.hasEnchantment(item, EnchantRegister.BLAST_MINING)) return false;
if (EnchantRegistry.VEINMINER != null && EnchantUtils.contains(item, EnchantRegistry.VEINMINER)) return false;
if (EnchantRegistry.BLAST_MINING != null && EnchantUtils.contains(item, EnchantRegistry.BLAST_MINING)) return false;
if (block.hasMetadata(META_BLOCK_TUNNEL)) return false;
if (block.getType().isInteractable() && !INTERACTABLE_BLOCKS.contains(block.getType())) return false;
if (block.getDrops(item).isEmpty()) return false;
@ -113,8 +115,12 @@ public class EnchantTunnel extends ExcellentEnchant implements BlockBreakEnchant
if (addType == Material.OBSIDIAN && addType != block.getType()) continue;
// Play block break particles before it's broken.
/*SimpleParticle.of(Particle.BLOCK_CRACK, blockAdd.getType())
.play(damager.getEyeLocation(), 0.25, 0.1, 20);
EffectUtil.playEffect(LocationUtil.getCenter(blockAdd.getLocation()), Particle.BLOCK_CRACK.name(), blockAdd.getType().name(), 0.2, 0.2, 0.2, 0.1, 20);
*/
// Add metadata to prevent enchantment triggering in a loop.
blockAdd.setMetadata(META_BLOCK_TUNNEL, new FixedMetadataValue(plugin, true));
//plugin.getNMS().breakBlock(player, blockAdd);

View File

@ -1,7 +1,7 @@
package su.nightexpress.excellentenchants.enchantment.impl.tool;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.enchantments.EnchantmentTarget;
@ -11,22 +11,19 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.utils.LocationUtil;
import su.nexmedia.engine.utils.Scaler;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.BlockBreakEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.EnchantRegister;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.type.FitItemType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.hook.impl.NoCheatPlusHook;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
@ -45,19 +42,39 @@ public class EnchantVeinminer extends ExcellentEnchant implements BlockBreakEnch
public EnchantVeinminer(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.HIGH);
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(EnchantBlastMining.ID, EnchantTunnel.ID);
}
@Override
public void loadConfig() {
super.loadConfig();
this.blocksLimit = EnchantScaler.read(this, "Settings.Blocks.Max_At_Once", "6 + " + Placeholders.ENCHANTMENT_LEVEL,
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.blocksAffected = JOption.create("Settings.Blocks.Affected", new HashSet<>(),
this.blocksAffected = JOption.forSet("Settings.Blocks.Affected",
str -> Material.getMaterial(str.toUpperCase()),
() -> {
Set<Material> set = new HashSet<>();
set.addAll(Tag.COAL_ORES.getValues());
set.addAll(Tag.COPPER_ORES.getValues());
set.addAll(Tag.DIAMOND_ORES.getValues());
set.addAll(Tag.EMERALD_ORES.getValues());
set.addAll(Tag.GOLD_ORES.getValues());
set.addAll(Tag.IRON_ORES.getValues());
set.addAll(Tag.LAPIS_ORES.getValues());
set.addAll(Tag.REDSTONE_ORES.getValues());
set.add(Material.NETHER_GOLD_ORE);
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").read(cfg).stream()
.map(type -> Material.getMaterial(type.toUpperCase())).filter(Objects::nonNull).collect(Collectors.toSet());
"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);
}
@NotNull
@ -111,7 +128,7 @@ public class EnchantVeinminer extends ExcellentEnchant implements BlockBreakEnch
ores.remove(source);
ores.forEach(ore -> {
// Play block break particles before the block broken.
EffectUtil.playEffect(LocationUtil.getCenter(ore.getLocation()), Particle.BLOCK_CRACK.name(), ore.getType().name(), 0.2, 0.2, 0.2, 0.1, 20);
//EffectUtil.playEffect(LocationUtil.getCenter(ore.getLocation()), Particle.BLOCK_CRACK.name(), ore.getType().name(), 0.2, 0.2, 0.2, 0.1, 20);
ore.setMetadata(META_BLOCK_VEINED, new FixedMetadataValue(plugin, true));
//plugin.getNMS().breakBlock(player, ore);
@ -123,8 +140,8 @@ public class EnchantVeinminer extends ExcellentEnchant implements BlockBreakEnch
@Override
public boolean onBreak(@NotNull BlockBreakEvent e, @NotNull Player player, @NotNull ItemStack tool, int level) {
if (!this.isAvailableToUse(player)) return false;
if (EnchantRegister.TUNNEL != null && EnchantManager.hasEnchantment(tool, EnchantRegister.TUNNEL)) return false;
if (EnchantRegister.BLAST_MINING != null && EnchantManager.hasEnchantment(tool, EnchantRegister.BLAST_MINING)) return false;
if (EnchantRegistry.TUNNEL != null && EnchantUtils.contains(tool, EnchantRegistry.TUNNEL)) return false;
if (EnchantRegistry.BLAST_MINING != null && EnchantUtils.contains(tool, EnchantRegistry.BLAST_MINING)) return false;
Block block = e.getBlock();
if (block.hasMetadata(META_BLOCK_VEINED)) return false;

View File

@ -12,9 +12,9 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
public class EnchantCurseOfFragility extends ExcellentEnchant {
@ -22,6 +22,9 @@ public class EnchantCurseOfFragility extends ExcellentEnchant {
public EnchantCurseOfFragility(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Prevents an item from being grindstoned or anviled.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0D);
}
@NotNull
@ -36,8 +39,8 @@ public class EnchantCurseOfFragility extends ExcellentEnchant {
ItemStack first = inventory.getItem(0);
ItemStack second = inventory.getItem(1);
boolean cursedFirst = (first != null && EnchantManager.getEnchantmentLevel(first, this) >= 1);
boolean cursedSecond = (second != null && EnchantManager.getEnchantmentLevel(second, this) >= 1);
boolean cursedFirst = (first != null && EnchantUtils.getLevel(first, this) >= 1);
boolean cursedSecond = (second != null && EnchantUtils.getLevel(second, this) >= 1);
if (cursedFirst || cursedSecond) {
e.setResult(null);
@ -65,8 +68,8 @@ public class EnchantCurseOfFragility extends ExcellentEnchant {
ItemStack first = inventory.getItem(0);
ItemStack second = inventory.getItem(1);
boolean cursedFirst = (first != null && EnchantManager.getEnchantmentLevel(first, this) >= 1);
boolean cursedSecond = (second != null && EnchantManager.getEnchantmentLevel(second, this) >= 1);
boolean cursedFirst = (first != null && EnchantUtils.getLevel(first, this) >= 1);
boolean cursedSecond = (second != null && EnchantUtils.getLevel(second, this) >= 1);
if (cursedFirst || cursedSecond) {
inventory.setItem(2, null);

View File

@ -8,14 +8,14 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.Set;
import java.util.function.UnaryOperator;
@ -38,6 +38,9 @@ public class EnchantBaneOfNetherspawn extends ExcellentEnchant implements Combat
public EnchantBaneOfNetherspawn(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Inflicts " + PLACEHOLDER_DAMAGE + " more damage to nether mobs.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(0.1);
}
@Override
@ -45,7 +48,8 @@ public class EnchantBaneOfNetherspawn extends ExcellentEnchant implements Combat
super.loadConfig();
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,
this.damageFormula = EnchantScaler.read(this, "Settings.Damage.Amount",
"0.5 * " + Placeholders.ENCHANTMENT_LEVEL,
"Amount of additional damage.");
}
@ -75,7 +79,7 @@ public class EnchantBaneOfNetherspawn extends ExcellentEnchant implements Combat
double damageAdd = this.getDamageModifier(level);
e.setDamage(this.damageModifier ? damageEvent * damageAdd : damageEvent + damageAdd);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.SMOKE_NORMAL, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.SMOKE_NORMAL).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -7,28 +7,39 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantBlindness extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.BLINDNESS, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -37,6 +48,12 @@ public class EnchantBlindness extends PotionEnchant implements Chanced, CombatEn
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -50,7 +67,7 @@ public class EnchantBlindness extends PotionEnchant implements Chanced, CombatEn
if (!this.addEffect(victim, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.SMOKE_NORMAL, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.SMOKE_NORMAL).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -8,28 +8,39 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantConfusion extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.CONFUSION, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -38,6 +49,12 @@ public class EnchantConfusion extends PotionEnchant implements Chanced, CombatEn
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -51,7 +68,8 @@ public class EnchantConfusion extends PotionEnchant implements Chanced, CombatEn
if (!this.addEffect(victim, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.ITEM_CRACK, Material.ROTTEN_FLESH.name(), 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.ITEM_CRACK, Material.ROTTEN_FLESH)
.play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -7,13 +7,14 @@ import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.Set;
@ -27,12 +28,16 @@ public class EnchantCure extends ExcellentEnchant implements Chanced, CombatEnch
public EnchantCure(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"20.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 8");
}
@NotNull
@ -57,7 +62,7 @@ public class EnchantCure extends ExcellentEnchant implements Chanced, CombatEnch
e.setCancelled(true);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.CLOUD, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.CLOUD).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
if (victim instanceof PigZombie pigZombie) {

View File

@ -11,18 +11,18 @@ 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.utils.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.MessageUtil;
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.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
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.util.EnchantPriority;
import java.util.function.UnaryOperator;
@ -36,13 +36,18 @@ public class EnchantCutter extends ExcellentEnchant implements Chanced, CombatEn
public EnchantCutter(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.LOWEST);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.durabilityReduction = EnchantScaler.read(this, "Settings.Item.Durability_Reduction", Placeholders.ENCHANTMENT_LEVEL + " / 100",
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",
"Amount (in percent) of how much item durability will be reduced.");
}
@ -99,7 +104,7 @@ public class EnchantCutter extends ExcellentEnchant implements Chanced, CombatEn
drop.getVelocity().multiply(3D);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.ITEM_CRACK.name(), itemCut.getType().name(), 0.2f, 0.15f, 0.2f, 0.15f, 40);
SimpleParticle.of(Particle.ITEM_CRACK, itemCut.getType()).play(victim.getEyeLocation(), 0.25, 0.15, 30);
MessageUtil.sound(victim.getLocation(), Sound.ENTITY_ITEM_BREAK);
}
return true;

View File

@ -18,6 +18,7 @@ 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.api.particle.SimpleParticle;
import su.nexmedia.engine.lang.LangManager;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.utils.ItemUtil;
@ -25,47 +26,131 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class EnchantDecapitator extends ExcellentEnchant implements Chanced, DeathEnchant {
public static final String ID = "decapitator";
private Set<String> ignoredEntityTypes;
private Set<EntityType> ignoredEntityTypes;
private String headName;
private Map<String, String> headTextures;
private Map<EntityType, String> headTextures;
private ChanceImplementation chanceImplementation;
private final NamespacedKey skullKey;
public EnchantDecapitator(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to obtain player''s or mob''s head.");
this.getDefaults().setLevelMax(4);
this.getDefaults().setTier(0.75);
this.skullKey = new NamespacedKey(plugin, this.getId() + ".entity_type");
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"5.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 1.75");
this.ignoredEntityTypes = JOption.create("Settings.Ignored_Entity_Types", new HashSet<>(),
"List of entities, that won't drop heads.").read(cfg).stream().map(String::toUpperCase).collect(Collectors.toSet());
this.ignoredEntityTypes = JOption.forSet("Settings.Ignored_Entity_Types",
str -> StringUtil.getEnum(str, EntityType.class).orElse(null),
() -> 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);
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.").read(cfg);
this.headTextures = new HashMap<>();
for (String sType : cfg.getSection("Settings.Head_Item.Textures")) {
this.headTextures = JOption.forMap("Settings.Head_Item.Textures",
id -> StringUtil.getEnum(id, EntityType.class).orElse(null),
(cfg, path, id) -> cfg.getString(path + "." + id),
() -> {
Map<EntityType, String> map = new HashMap<>();
map.put(EntityType.AXOLOTL, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNThkYTFhMGEyYTEzZGQyMDliZmMyNTI5ZDljN2MyOWEyOWRkOWEyM2ZmNGI4MGIzOGI4OTk2MTc3MmU4MDM5ZSJ9fX0=");
map.put(EntityType.BAT, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWU5OWRlZWY5MTlkYjY2YWMyYmQyOGQ2MzAyNzU2Y2NkNTdjN2Y4YjEyYjlkY2E4ZjQxYzNlMGEwNGFjMWNjIn19fQ==");
map.put(EntityType.BEE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTI3MjRhOWE0Y2RkNjhiYTQ5NDE1NTYwZTViZTQwYjRhMWM0N2NiNWJlMWQ2NmFlZGI1MmEzMGU2MmVmMmQ0NyJ9fX0=");
map.put(EntityType.BLAZE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjc4ZWYyZTRjZjJjNDFhMmQxNGJmZGU5Y2FmZjEwMjE5ZjViMWJmNWIzNWE0OWViNTFjNjQ2Nzg4MmNiNWYwIn19fQ==");
map.put(EntityType.CAT, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTRiNDVjYmFhMTlmZTNkNjhjODU2Y2QzODQ2YzAzYjVmNTlkZTgxYTQ4MGVlYzkyMWFiNGZhM2NkODEzMTcifX19");
map.put(EntityType.CAVE_SPIDER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTYxN2Y3ZGQ1ZWQxNmYzYmQxODY0NDA1MTdjZDQ0MGExNzAwMTViMWNjNmZjYjJlOTkzYzA1ZGUzM2YifX19");
map.put(EntityType.CHICKEN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTYzODQ2OWE1OTljZWVmNzIwNzUzNzYwMzI0OGE5YWIxMWZmNTkxZmQzNzhiZWE0NzM1YjM0NmE3ZmFlODkzIn19fQ==");
map.put(EntityType.COD, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg5MmQ3ZGQ2YWFkZjM1Zjg2ZGEyN2ZiNjNkYTRlZGRhMjExZGY5NmQyODI5ZjY5MTQ2MmE0ZmIxY2FiMCJ9fX0=");
map.put(EntityType.COW, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2RmYTBhYzM3YmFiYTJhYTI5MGU0ZmFlZTQxOWE2MTNjZDYxMTdmYTU2OGU3MDlkOTAzNzQ3NTNjMDMyZGNiMCJ9fX0=");
map.put(EntityType.DOLPHIN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGU5Njg4Yjk1MGQ4ODBiNTViN2FhMmNmY2Q3NmU1YTBmYTk0YWFjNmQxNmY3OGU4MzNmNzQ0M2VhMjlmZWQzIn19fQ==");
map.put(EntityType.DONKEY, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjNhOTc2YzA0N2Y0MTJlYmM1Y2IxOTcxMzFlYmVmMzBjMDA0YzBmYWY0OWQ4ZGQ0MTA1ZmNhMTIwN2VkYWZmMyJ9fX0=");
map.put(EntityType.DROWNED, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzNmN2NjZjYxZGJjM2Y5ZmU5YTYzMzNjZGUwYzBlMTQzOTllYjJlZWE3MWQzNGNmMjIzYjNhY2UyMjA1MSJ9fX0=");
map.put(EntityType.ELDER_GUARDIAN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWM3OTc0ODJhMTRiZmNiODc3MjU3Y2IyY2ZmMWI2ZTZhOGI4NDEzMzM2ZmZiNGMyOWE2MTM5Mjc4YjQzNmIifX19");
map.put(EntityType.ENDERMAN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjMGIzNmQ1M2ZmZjY5YTQ5YzdkNmYzOTMyZjJiMGZlOTQ4ZTAzMjIyNmQ1ZTgwNDVlYzU4NDA4YTM2ZTk1MSJ9fX0=");
map.put(EntityType.ENDERMITE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWExYTA4MzFhYTAzYWZiNDIxMmFkY2JiMjRlNWRmYWE3ZjQ3NmExMTczZmNlMjU5ZWY3NWE4NTg1NSJ9fX0=");
map.put(EntityType.EVOKER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDk1NDEzNWRjODIyMTM5NzhkYjQ3ODc3OGFlMTIxMzU5MWI5M2QyMjhkMzZkZDU0ZjFlYTFkYTQ4ZTdjYmE2In19fQ==");
map.put(EntityType.FOX, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDg5NTRhNDJlNjllMDg4MWFlNmQyNGQ0MjgxNDU5YzE0NGEwZDVhOTY4YWVkMzVkNmQzZDczYTNjNjVkMjZhIn19fQ==");
map.put(EntityType.GHAST, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGU4YTM4ZTlhZmJkM2RhMTBkMTliNTc3YzU1YzdiZmQ2YjRmMmU0MDdlNDRkNDAxN2IyM2JlOTE2N2FiZmYwMiJ9fX0=");
map.put(EntityType.GOAT, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDU3YTBkNTM4ZmEwOGE3YWZmZTMxMjkwMzQ2ODg2MTcyMGY5ZmEzNGU4NmQ0NGI4OWRjZWM1NjM5MjY1ZjAzIn19fQ==");
map.put(EntityType.GUARDIAN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTBiZjM0YTcxZTc3MTViNmJhNTJkNWRkMWJhZTVjYjg1Zjc3M2RjOWIwZDQ1N2I0YmZjNWY5ZGQzY2M3Yzk0In19fQ==");
map.put(EntityType.HOGLIN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWJiOWJjMGYwMWRiZDc2MmEwOGQ5ZTc3YzA4MDY5ZWQ3Yzk1MzY0YWEzMGNhMTA3MjIwODU2MWI3MzBlOGQ3NSJ9fX0=");
map.put(EntityType.HORSE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjY2YjJiMzJkMzE1MzljNzM4M2Q5MjNiYWU0ZmFhZjY1ZGE2NzE1Y2Q1MjZjMzVkMmU0ZTY4MjVkYTExZmIifX19");
map.put(EntityType.HUSK, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY3NGM2M2M4ZGI1ZjRjYTYyOGQ2OWEzYjFmOGEzNmUyOWQ4ZmQ3NzVlMWE2YmRiNmNhYmI0YmU0ZGIxMjEifX19");
map.put(EntityType.ILLUSIONER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmYyODgyZGQwOTcyM2U0N2MwYWI5NjYzZWFiMDgzZDZhNTk2OTI3MzcwNjExMGM4MjkxMGU2MWJmOGE4ZjA3ZSJ9fX0=");
map.put(EntityType.IRON_GOLEM, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODkwOTFkNzllYTBmNTllZjdlZjk0ZDdiYmE2ZTVmMTdmMmY3ZDQ1NzJjNDRmOTBmNzZjNDgxOWE3MTQifX19");
map.put(EntityType.LLAMA, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODNkOWI1OTE1OTEyZmZjMmI4NTc2MWQ2YWRjYjQyOGE4MTJmOWI4M2ZmNjM0ZTMzMTE2MmNlNDZjOTllOSJ9fX0=");
map.put(EntityType.MAGMA_CUBE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTFjOTdhMDZlZmRlMDRkMDAyODdiZjIwNDE2NDA0YWIyMTAzZTEwZjA4NjIzMDg3ZTFiMGMxMjY0YTFjMGYwYyJ9fX0=");
map.put(EntityType.MULE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDZkY2RhMjY1ZTU3ZTRmNTFiMTQ1YWFjYmY1YjU5YmRjNjA5OWZmZDNjY2UwYTY2MWIyYzAwNjVkODA5MzBkOCJ9fX0=");
map.put(EntityType.MUSHROOM_COW, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmI1Mjg0MWYyZmQ1ODllMGJjODRjYmFiZjllMWMyN2NiNzBjYWM5OGY4ZDZiM2RkMDY1ZTU1YTRkY2I3MGQ3NyJ9fX0=");
map.put(EntityType.OCELOT, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTY1N2NkNWMyOTg5ZmY5NzU3MGZlYzRkZGNkYzY5MjZhNjhhMzM5MzI1MGMxYmUxZjBiMTE0YTFkYjEifX19");
map.put(EntityType.PANDA, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDE4OGM5ODBhYWNmYTk0Y2YzMzA4ODUxMmIxYjk1MTdiYTgyNmIxNTRkNGNhZmMyNjJhZmY2OTc3YmU4YSJ9fX0=");
map.put(EntityType.PARROT, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjBiZmE4NTBmNWRlNGIyOTgxY2NlNzhmNTJmYzJjYzdjZDdiNWM2MmNhZWZlZGRlYjljZjMxMWU4M2Q5MDk3In19fQ==");
map.put(EntityType.PHANTOM, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDExZDI1YmNkYWJhZmFkNWZkNmUwMTBjNWIxY2Y3YTAwYzljY2E0MGM1YTQ2NzQ3ZjcwNmRjOWNiM2EifX19");
map.put(EntityType.PIG, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWEzNzFhMDZlYTc4NThmODlkMjdjYzEwNTVjMzE3YjIzZjEwNWM5MTI1YmM1MTZkMzg5MWFhNGM4MzVjMjk5In19fQ==");
map.put(EntityType.PIGLIN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2NlZDlkODAxYWE2ZjgzZjhlNDlmOTBkOWE4Yjg1YjdmOGZkYTU4M2Q4NWY3MmNmZmI2OTg2NzI1Nzg5ZjYzNiJ9fX0=");
map.put(EntityType.PIGLIN_BRUTE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2NlZDlkODAxYWE2ZjgzZjhlNDlmOTBkOWE4Yjg1YjdmOGZkYTU4M2Q4NWY3MmNmZmI2OTg2NzI1Nzg5ZjYzNiJ9fX0=");
map.put(EntityType.PILLAGER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGFlZTZiYjM3Y2JmYzkyYjBkODZkYjVhZGE0NzkwYzY0ZmY0NDY4ZDY4Yjg0OTQyZmRlMDQ0MDVlOGVmNTMzMyJ9fX0=");
map.put(EntityType.POLAR_BEAR, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzRmZTkyNjkyMmZiYjQwNmYzNDNiMzRhMTBiYjk4OTkyY2VlNDQxMDEzN2QzZjg4MDk5NDI3YjIyZGUzYWI5MCJ9fX0=");
map.put(EntityType.PUFFERFISH, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjkyMzUwYzlmMDk5M2VkNTRkYjJjNzExMzkzNjMyNTY4M2ZmYzIwMTA0YTliNjIyYWE0NTdkMzdlNzA4ZDkzMSJ9fX0=");
map.put(EntityType.RABBIT, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzk3N2EzMjY2YmYzYjllYWYxN2U1YTAyZWE1ZmJiNDY4MDExNTk4NjNkZDI4OGI5M2U2YzEyYzljYiJ9fX0=");
map.put(EntityType.RAVAGER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2QyMGJmNTJlYzM5MGEwNzk5Mjk5MTg0ZmM2NzhiZjg0Y2Y3MzJiYjFiZDc4ZmQxYzRiNDQxODU4ZjAyMzVhOCJ9fX0=");
map.put(EntityType.SALMON, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjBlYTlhMjIzNjIwY2RiNTRiMzU3NDEzZDQzYmQ4OWM0MDA4YmNhNmEyMjdmM2I3ZGI5N2Y3NzMzZWFkNWZjZiJ9fX0=");
map.put(EntityType.SHEEP, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMxZjljY2M2YjNlMzJlY2YxM2I4YTExYWMyOWNkMzNkMThjOTVmYzczZGI4YTY2YzVkNjU3Y2NiOGJlNzAifX19");
map.put(EntityType.SILVERFISH, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGE5MWRhYjgzOTFhZjVmZGE1NGFjZDJjMGIxOGZiZDgxOWI4NjVlMWE4ZjFkNjIzODEzZmE3NjFlOTI0NTQwIn19fQ==");
map.put(EntityType.SLIME, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0=");
map.put(EntityType.SNOWMAN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGU4ZDIwNmY2MWU2ZGU4YTc5ZDBjYjBiY2Q5OGFjZWQ0NjRjYmZlZmM5MjFiNDE2MGEyNTI4MjE2MzExMmEifX19");
map.put(EntityType.SPIDER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ==");
map.put(EntityType.SQUID, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDljMmM5Y2U2N2ViNTk3MWNjNTk1ODQ2M2U2YzlhYmFiOGU1OTlhZGMyOTVmNGQ0MjQ5OTM2YjAwOTU3NjlkZCJ9fX0=");
map.put(EntityType.STRAY, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmM1MDk3OTE2YmMwNTY1ZDMwNjAxYzBlZWJmZWIyODcyNzdhMzRlODY3YjRlYTQzYzYzODE5ZDUzZTg5ZWRlNyJ9fX0=");
map.put(EntityType.STRIDER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2I3ZmZkZGE2NTZjNjhkODg4NTFhOGUwNWI0OGNkMjQ5Mzc3M2ZmYzRhYjdkNjRlOTMwMjIyOWZlMzU3MTA1OSJ9fX0=");
map.put(EntityType.TRADER_LLAMA, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODQyNDc4MGIzYzVjNTM1MWNmNDlmYjViZjQxZmNiMjg5NDkxZGY2YzQzMDY4M2M4NGQ3ODQ2MTg4ZGI0Zjg0ZCJ9fX0=");
map.put(EntityType.TROPICAL_FISH, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDZkZDVlNmFkZGI1NmFjYmM2OTRlYTRiYTU5MjNiMWIyNTY4ODE3OGZlZmZhNzIyOTAyOTllMjUwNWM5NzI4MSJ9fX0=");
map.put(EntityType.TURTLE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMGE0MDUwZTdhYWNjNDUzOTIwMjY1OGZkYzMzOWRkMTgyZDdlMzIyZjlmYmNjNGQ1Zjk5YjU3MThhIn19fQ==");
map.put(EntityType.VEX, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzJlYzVhNTE2NjE3ZmYxNTczY2QyZjlkNWYzOTY5ZjU2ZDU1NzVjNGZmNGVmZWZhYmQyYTE4ZGM3YWI5OGNkIn19fQ==");
map.put(EntityType.VILLAGER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDFiODMwZWI0MDgyYWNlYzgzNmJjODM1ZTQwYTExMjgyYmI1MTE5MzMxNWY5MTE4NDMzN2U4ZDM1NTU1ODMifX19");
map.put(EntityType.VINDICATOR, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmRlYWVjMzQ0YWIwOTViNDhjZWFkNzUyN2Y3ZGVlNjFiMDYzZmY3OTFmNzZhOGZhNzY2NDJjODY3NmUyMTczIn19fQ==");
map.put(EntityType.WANDERING_TRADER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWYxMzc5YTgyMjkwZDdhYmUxZWZhYWJiYzcwNzEwZmYyZWMwMmRkMzRhZGUzODZiYzAwYzkzMGM0NjFjZjkzMiJ9fX0=");
map.put(EntityType.WITCH, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjBlMTNkMTg0NzRmYzk0ZWQ1NWFlYjcwNjk1NjZlNDY4N2Q3NzNkYWMxNmY0YzNmODcyMmZjOTViZjlmMmRmYSJ9fX0=");
map.put(EntityType.WOLF, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA0OThkZTZmNWIwOWUwY2UzNWE3MjkyZmU1MGI3OWZjZTkwNjVkOWJlOGUyYTg3YzdhMTM1NjZlZmIyNmQ3MiJ9fX0=");
map.put(EntityType.ZOGLIN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTY3ZTE4NjAyZTAzMDM1YWQ2ODk2N2NlMDkwMjM1ZDg5OTY2NjNmYjllYTQ3NTc4ZDNhN2ViYmM0MmE1Y2NmOSJ9fX0=");
map.put(EntityType.ZOMBIFIED_PIGLIN, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2VhYmFlY2M1ZmFlNWE4YTQ5Yzg4NjNmZjQ4MzFhYWEyODQxOThmMWEyMzk4ODkwYzc2NWUwYThkZTE4ZGE4YyJ9fX0=");
map.put(EntityType.ZOMBIE_HORSE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDIyOTUwZjJkM2VmZGRiMThkZTg2ZjhmNTVhYzUxOGRjZTczZjEyYTZlMGY4NjM2ZDU1MWQ4ZWI0ODBjZWVjIn19fQ==");
map.put(EntityType.ZOMBIE_VILLAGER, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMDhhODc3NmMxNzY0YzNmZTZhNmRkZDQxMmRmY2I4N2Y0MTMzMWRhZDQ3OWFjOTZjMjFkZjRiZjNhYzg5YyJ9fX0=");
map.put(EntityType.SKELETON_HORSE, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDdlZmZjZTM1MTMyYzg2ZmY3MmJjYWU3N2RmYmIxZDIyNTg3ZTk0ZGYzY2JjMjU3MGVkMTdjZjg5NzNhIn19fQ==");
return map;
},
"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",
@ -73,7 +158,7 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea
"You can take some from http://minecraft-heads.com",
"https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html");
/*this.headTextures = new JOption<Map<String, String>>("Settings.Head_Item.Textures",
this.headTextures = new JOption<Map<String, String>>("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.",
@ -103,7 +188,7 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea
if (!this.isAvailableToUse(entity)) return false;
EntityType entityType = entity.getType();
if (this.ignoredEntityTypes.contains(entityType.name())) return false;
if (this.ignoredEntityTypes.contains(entityType)) return false;
if (!this.checkTriggerChance(level)) return false;
ItemStack item;
@ -133,7 +218,7 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea
meta.setOwningPlayer(player);
}
else {
String texture = this.headTextures.get(entity.getType().name());
String texture = this.headTextures.get(entity.getType());
if (texture == null) return false;
entityName = this.headName.replace(Placeholders.GENERIC_TYPE, plugin.getLangManager().getEnum(entity.getType()));
@ -149,7 +234,7 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea
entity.getWorld().dropItemNaturally(entity.getLocation(), item);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(entity.getEyeLocation(), Particle.BLOCK_CRACK, Material.REDSTONE_BLOCK.name(), 0.2f, 0.15f, 0.2f, 0.15f, 40);
SimpleParticle.of(Particle.BLOCK_CRACK, Material.REDSTONE_BLOCK).play(entity.getEyeLocation(), 0.25, 0.15, 30);
}
return true;
}
@ -170,12 +255,12 @@ public class EnchantDecapitator extends ExcellentEnchant implements Chanced, Dea
if (!(e.getBlockState() instanceof Skull skull)) return;
PDCUtil.getString(skull, this.skullKey).ifPresent(type -> {
String texture = this.headTextures.get(type);
if (texture == null) return;
EntityType entityType = StringUtil.getEnum(type, EntityType.class).orElse(null);
if (entityType == null) return;
String texture = this.headTextures.get(entityType);
if (texture == null) return;
e.getItems().forEach(item -> {
ItemStack drop = item.getItemStack();
if (drop.getType() == Material.PLAYER_HEAD) {

View File

@ -7,14 +7,15 @@ 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.utils.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.MessageUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
public class EnchantDoubleStrike extends ExcellentEnchant implements Chanced, CombatEnchant {
@ -24,12 +25,16 @@ public class EnchantDoubleStrike extends ExcellentEnchant implements Chanced, Co
public EnchantDoubleStrike(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.LOW);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to inflict double damage.");
this.getDefaults().setLevelMax(4);
this.getDefaults().setTier(1.0);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"4.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.8");
}
@NotNull
@ -52,7 +57,7 @@ public class EnchantDoubleStrike extends ExcellentEnchant implements Chanced, Co
e.setDamage(e.getDamage() * 2D);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.EXPLOSION_NORMAL, "", 0.2f, 0.15f, 0.2f, 0.15f, 20);
SimpleParticle.of(Particle.EXPLOSION_NORMAL).play(victim.getEyeLocation(), 0.25, 0.15, 15);
MessageUtil.sound(victim.getLocation(), Sound.ENTITY_GENERIC_EXPLODE);
}
return true;

View File

@ -1,5 +1,6 @@
package su.nightexpress.excellentenchants.enchantment.impl.weapon;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.LivingEntity;
@ -7,28 +8,39 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantExhaust extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.HUNGER, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -37,6 +49,12 @@ public class EnchantExhaust extends PotionEnchant implements Chanced, CombatEnch
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -50,7 +68,7 @@ public class EnchantExhaust extends PotionEnchant implements Chanced, CombatEnch
if (!this.addEffect(victim, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.SPELL_MOB, "60,180,20", 0.2f, 0.15f, 0.2f, 0.15f, 20);
SimpleParticle.of(Particle.ITEM_CRACK, Material.ROTTEN_FLESH).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -8,9 +8,9 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import java.util.function.UnaryOperator;
@ -24,12 +24,16 @@ public class EnchantExpHunter extends ExcellentEnchant implements DeathEnchant {
public EnchantExpHunter(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Increases exp drop from mobs by " + PLACEHOLDER_EXP_MODIFIER + "%.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(0.3);
}
@Override
public void loadConfig() {
super.loadConfig();
this.expModifier = EnchantScaler.read(this, "Settings.Exp_Modifier", "1.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 0.5",
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.");
}

View File

@ -8,18 +8,50 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
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.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantIceAspect extends PotionEnchant implements CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.SLOW, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
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
@ -31,12 +63,13 @@ public class EnchantIceAspect extends PotionEnchant implements CombatEnchant {
@Override
public boolean onAttack(@NotNull EntityDamageByEntityEvent e, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) {
if (!this.isAvailableToUse(damager)) return false;
if (!this.checkTriggerChance(level)) return false;
if (!this.addEffect(victim, level)) return false;
victim.setFreezeTicks(victim.getMaxFreezeTicks());
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.BLOCK_CRACK, Material.ICE.name(), 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.BLOCK_CRACK, Material.ICE).play(victim.getEyeLocation(), 0.25, 0.15, 30);
}
return true;
}

View File

@ -13,10 +13,10 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.function.UnaryOperator;
@ -29,12 +29,16 @@ public class EnchantInfernus extends ExcellentEnchant {
public EnchantInfernus(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.fireTicks = EnchantScaler.read(this, "Settings.Fire_Ticks", "60 + " + Placeholders.ENCHANTMENT_LEVEL + " * 20",
this.fireTicks = EnchantScaler.read(this, "Settings.Fire_Ticks",
"60 + " + Placeholders.ENCHANTMENT_LEVEL + " * 20",
"Sets for how long (in ticks) entity will be ignited on hit. 20 ticks = 1 second.");
}
@ -65,7 +69,7 @@ public class EnchantInfernus extends ExcellentEnchant {
ItemStack item = trident.getItem();
int level = EnchantManager.getEnchantmentLevel(item, this);
int level = EnchantUtils.getLevel(item, this);
if (level <= 0) return;
trident.setFireTicks(Integer.MAX_VALUE);
@ -78,7 +82,7 @@ public class EnchantInfernus extends ExcellentEnchant {
ItemStack item = trident.getItem();
int level = EnchantManager.getEnchantmentLevel(item, this);
int level = EnchantUtils.getLevel(item, this);
if (level <= 0 || trident.getFireTicks() <= 0) return;
int ticks = this.getFireTicks(level);

View File

@ -7,10 +7,10 @@ import org.bukkit.event.entity.EntityDeathEvent;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.utils.PlayerUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.DeathEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
public class EnchantNimble extends ExcellentEnchant implements Chanced, DeathEnchant {
@ -21,6 +21,9 @@ public class EnchantNimble extends ExcellentEnchant implements Chanced, DeathEnc
public EnchantNimble(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.LOWEST);
this.getDefaults().setDescription("Moves all mob's loot directly to your inventory.");
this.getDefaults().setLevelMax(1);
this.getDefaults().setTier(0.4);
}
@Override

View File

@ -7,28 +7,39 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantParalyze extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.SLOW_DIGGING, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -37,6 +48,12 @@ public class EnchantParalyze extends PotionEnchant implements Chanced, CombatEnc
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -50,7 +67,7 @@ public class EnchantParalyze extends PotionEnchant implements Chanced, CombatEnc
if (!this.addEffect(victim, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.CRIT_MAGIC, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.CRIT_MAGIC).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -7,28 +7,39 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantRage extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.INCREASE_DAMAGE, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -37,6 +48,12 @@ public class EnchantRage extends PotionEnchant implements Chanced, CombatEnchant
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -50,7 +67,7 @@ public class EnchantRage extends PotionEnchant implements Chanced, CombatEnchant
if (!this.addEffect(damager, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(damager.getEyeLocation(), Particle.LAVA, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.LAVA).play(damager.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -1,23 +1,24 @@
package su.nightexpress.excellentenchants.enchantment.impl.weapon;
import org.bukkit.Sound;
import org.bukkit.*;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.entity.LivingEntity;
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.EntityUtil;
import su.nexmedia.engine.utils.MessageUtil;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
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.util.EnchantPriority;
public class EnchantRocket extends ExcellentEnchant implements Chanced, CombatEnchant {
@ -28,13 +29,18 @@ public class EnchantRocket extends ExcellentEnchant implements Chanced, CombatEn
public EnchantRocket(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription(Placeholders.ENCHANTMENT_CHANCE + "% chance to launch your enemy into the space.");
this.getDefaults().setLevelMax(3);
this.getDefaults().setTier(0.5);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.fireworkPower = EnchantScaler.read(this, "Settings.Firework_Power", Placeholders.ENCHANTMENT_LEVEL + " * 0.25",
this.chanceImplementation = ChanceImplementation.create(this,
"4.0 + " + Placeholders.ENCHANTMENT_LEVEL);
this.fireworkPower = EnchantScaler.read(this, "Settings.Firework_Power",
Placeholders.ENCHANTMENT_LEVEL + " * 0.25",
"Firework power. The more power = the higher fly distance.");
}
@ -63,16 +69,32 @@ public class EnchantRocket extends ExcellentEnchant implements Chanced, CombatEn
victim.leaveVehicle();
}
Firework firework = EntityUtil.spawnRandomFirework(victim.getLocation());
FireworkMeta meta = firework.getFireworkMeta();
meta.setPower((int) this.getFireworkPower(level));
firework.setFireworkMeta(meta);
Firework firework = this.createRocket(victim.getLocation(), level);
firework.addPassenger(victim);
MessageUtil.sound(victim.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_LAUNCH);
return true;
}
@NotNull
private Firework createRocket(@NotNull Location location, int level) {
World world = location.getWorld();
if (world == null) {
throw new IllegalStateException("World is null!");
}
Firework firework = (Firework) world.spawnEntity(location, EntityType.FIREWORK);
FireworkMeta meta = firework.getFireworkMeta();
FireworkEffect.Type type = Rnd.get(FireworkEffect.Type.values());
Color color = Color.fromBGR(Rnd.nextInt(255), Rnd.nextInt(255), Rnd.nextInt(255));
Color fade = Color.fromBGR(Rnd.nextInt(255), Rnd.nextInt(255), Rnd.nextInt(255));
FireworkEffect effect = FireworkEffect.builder().flicker(Rnd.nextBoolean()).withColor(color).withFade(fade).with(type).trail(Rnd.nextBoolean()).build();
meta.addEffect(effect);
meta.setPower((int) this.getFireworkPower(level));
firework.setFireworkMeta(meta);
return firework;
}
@Override
public boolean onProtect(@NotNull EntityDamageByEntityEvent e, @NotNull LivingEntity damager, @NotNull LivingEntity victim, @NotNull ItemStack weapon, int level) {
return false;

View File

@ -8,16 +8,16 @@ import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.utils.CollectionsUtil;
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.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.HashMap;
import java.util.Map;
@ -27,20 +27,36 @@ public class EnchantScavenger extends ExcellentEnchant implements Chanced, Death
public static final String ID = "scavenger";
private Map<EntityType, Map<Material, Pair<int[], Double>>> loot;
private ChanceImplementation chanceImplementation;
public EnchantScavenger(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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 = CollectionsUtil.getEnum(eId, EntityType.class);
EntityType eType = StringUtil.getEnum(eId, EntityType.class).orElse(null);
if (eType == null || !eType.isAlive()) {
plugin.error("[Scavenger] Invalid entity type '" + eId + "' !");
continue;

View File

@ -12,26 +12,37 @@ import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.impl.meta.PotionImplementation;
public class EnchantSurprise extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.BLINDNESS, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -40,6 +51,12 @@ public class EnchantSurprise extends PotionEnchant implements Chanced, CombatEnc
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {

View File

@ -10,9 +10,9 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import java.util.function.UnaryOperator;
@ -30,12 +30,16 @@ public class EnchantTemper extends ExcellentEnchant implements CombatEnchant {
public EnchantTemper(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.damageAmount = EnchantScaler.read(this, "Settings.Damage.Amount", "0.01 * " + Placeholders.ENCHANTMENT_LEVEL,
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.");

View File

@ -13,14 +13,15 @@ import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JOption;
import su.nexmedia.engine.utils.CollectionsUtil;
import su.nexmedia.engine.utils.PDCUtil;
import su.nexmedia.engine.utils.StringUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
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.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.Objects;
import java.util.Set;
@ -38,19 +39,24 @@ public class EnchantThrifty extends ExcellentEnchant implements Chanced, DeathEn
public EnchantThrifty(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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 -> CollectionsUtil.getEnum(e, EntityType.class))
.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",
@ -59,7 +65,7 @@ public class EnchantThrifty extends ExcellentEnchant implements Chanced, DeathEn
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 -> CollectionsUtil.getEnum(e, CreatureSpawnEvent.SpawnReason.class))
.read(cfg).stream().map(e -> StringUtil.getEnum(e, CreatureSpawnEvent.SpawnReason.class).orElse(null))
.filter(Objects::nonNull).collect(Collectors.toSet());
}

View File

@ -11,10 +11,11 @@ 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.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
public class EnchantThunder extends ExcellentEnchant implements Chanced, CombatEnchant {
@ -28,12 +29,16 @@ public class EnchantThunder extends ExcellentEnchant implements Chanced, CombatE
public EnchantThunder(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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);
}

View File

@ -9,17 +9,17 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
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.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.impl.meta.ChanceImplementation;
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.util.EnchantPriority;
import java.util.function.UnaryOperator;
@ -34,14 +34,19 @@ public class EnchantVampire extends ExcellentEnchant implements Chanced, CombatE
public EnchantVampire(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.LOWEST);
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);
}
@Override
public void loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
this.chanceImplementation = ChanceImplementation.create(this,
"25.0 + " + Placeholders.ENCHANTMENT_LEVEL + " * 5.0");
this.healAmount = EnchantScaler.read(this, "Settings.Heal.Amount", "0.25 * " + Placeholders.ENCHANTMENT_LEVEL,
this.healAmount = EnchantScaler.read(this, "Settings.Heal.Amount",
"0.25 * " + Placeholders.ENCHANTMENT_LEVEL,
"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);
@ -97,7 +102,7 @@ public class EnchantVampire extends ExcellentEnchant implements Chanced, CombatE
damager.setHealth(Math.min(healthMax, healthHas + healthEvent.getAmount()));
if (this.hasVisualEffects()) {
EffectUtil.playEffect(damager.getEyeLocation(), Particle.HEART, "", 0.2f, 0.15f, 0.2f, 0.15f, 5);
SimpleParticle.of(Particle.HEART).play(damager.getEyeLocation(), 0.25, 0.15, 5);
}
return true;
}

View File

@ -7,28 +7,39 @@ 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.EffectUtil;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantVenom extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.POISON, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -37,6 +48,12 @@ public class EnchantVenom extends PotionEnchant implements Chanced, CombatEnchan
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -50,7 +67,7 @@ public class EnchantVenom extends PotionEnchant implements Chanced, CombatEnchan
if (!this.addEffect(victim, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.SLIME, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.SLIME).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -8,14 +8,15 @@ 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.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.utils.NumberUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
import su.nightexpress.excellentenchants.enchantment.config.EnchantScaler;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantPriority;
import java.util.function.UnaryOperator;
@ -29,13 +30,17 @@ public class EnchantVillageDefender extends ExcellentEnchant implements CombatEn
public EnchantVillageDefender(@NotNull ExcellentEnchants plugin) {
super(plugin, ID, EnchantPriority.MEDIUM);
this.getDefaults().setDescription("Inflicts " + PLACEHOLDER_DAMAGE_AMOUNT + " more damage to all pillagers.");
this.getDefaults().setLevelMax(5);
this.getDefaults().setTier(0.1);
}
@Override
public void loadConfig() {
super.loadConfig();
this.damageAmount = EnchantScaler.read(this, "Settings.Damage.Formula", "0.5 * " + Placeholders.ENCHANTMENT_LEVEL,
this.damageAmount = EnchantScaler.read(this, "Settings.Damage.Formula",
"0.5 * " + Placeholders.ENCHANTMENT_LEVEL,
"Amount of additional damage.");
this.damageMultiplier = JOption.create("Settings.Damage.As_Modifier", false,
@ -76,7 +81,7 @@ public class EnchantVillageDefender extends ExcellentEnchant implements CombatEn
e.setDamage(damageFinal);
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.VILLAGER_ANGRY, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.VILLAGER_ANGRY).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -7,28 +7,40 @@ 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.api.particle.SimpleParticle;
import su.nexmedia.engine.utils.EffectUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.meta.Chanced;
import su.nightexpress.excellentenchants.api.enchantment.template.PotionEnchant;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.CombatEnchant;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantPriority;
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.util.EnchantPriority;
public class EnchantWither extends PotionEnchant implements Chanced, CombatEnchant {
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, EnchantPriority.MEDIUM, PotionEffectType.WITHER, false);
super(plugin, ID, EnchantPriority.MEDIUM);
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 loadConfig() {
super.loadConfig();
this.chanceImplementation = ChanceImplementation.create(this);
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
@ -37,6 +49,12 @@ public class EnchantWither extends PotionEnchant implements Chanced, CombatEncha
return chanceImplementation;
}
@NotNull
@Override
public PotionImplementation getPotionImplementation() {
return potionImplementation;
}
@NotNull
@Override
public EnchantmentTarget getItemTarget() {
@ -50,7 +68,7 @@ public class EnchantWither extends PotionEnchant implements Chanced, CombatEncha
if (!this.addEffect(victim, level)) return false;
if (this.hasVisualEffects()) {
EffectUtil.playEffect(victim.getEyeLocation(), Particle.ASH, "", 0.25, 0.25, 0.25, 0.1f, 30);
SimpleParticle.of(Particle.ASH).play(victim.getEyeLocation(), 0.25, 0.1, 30);
}
return true;
}

View File

@ -16,8 +16,8 @@ import su.nexmedia.engine.utils.MessageUtil;
import su.nexmedia.engine.utils.PDCUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.HashMap;
import java.util.Map;
@ -46,7 +46,7 @@ public class EnchantAnvilListener extends AbstractListener<ExcellentEnchants> {
if (result == null) result = new ItemStack(Material.AIR);
// Check if source item is an enchantable single item.
if (first.getType().isAir() || first.getAmount() > 1 || !EnchantManager.isEnchantable(first)) return;
if (first.getType().isAir() || first.getAmount() > 1 || !EnchantUtils.isEnchantable(first)) return;
if (this.handleRename(e, first, second, result)) return;
if (this.handleRecharge(e, first, second, result)) return;
@ -61,10 +61,10 @@ public class EnchantAnvilListener extends AbstractListener<ExcellentEnchants> {
if (result.getType() != first.getType()) return false;
ItemStack result2 = new ItemStack(result);
EnchantManager.getExcellentEnchantments(first).forEach((hasEnch, hasLevel) -> {
EnchantManager.addEnchantment(result2, hasEnch, hasLevel, true);
EnchantUtils.getExcellents(first).forEach((hasEnch, hasLevel) -> {
EnchantUtils.add(result2, hasEnch, hasLevel, true);
});
EnchantManager.updateEnchantmentsDisplay(result2);
EnchantUtils.updateDisplay(result2);
e.setResult(result2);
return true;
}
@ -73,7 +73,7 @@ public class EnchantAnvilListener extends AbstractListener<ExcellentEnchants> {
@NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) {
if (second.getType().isAir()) return false;
Set<ExcellentEnchant> chargeables = EnchantManager.getExcellentEnchantments(first).keySet().stream()
Set<ExcellentEnchant> chargeables = EnchantUtils.getExcellents(first).keySet().stream()
.filter(en -> en.isChargesEnabled() && en.isChargesFuel(second) && !en.isFullOfCharges(first))
.collect(Collectors.toSet());
if (chargeables.isEmpty()) return false;
@ -82,31 +82,31 @@ public class EnchantAnvilListener extends AbstractListener<ExcellentEnchants> {
int count = 0;
while (count < second.getAmount() && !chargeables.stream().allMatch(en -> en.isFullOfCharges(result2))) {
chargeables.forEach(enchant -> EnchantManager.rechargeEnchantmentCharges(result2, enchant));
chargeables.forEach(enchant -> EnchantUtils.rechargeCharges(result2, enchant));
count++;
}
PDCUtil.set(result2, RECHARGED, count);
EnchantManager.updateEnchantmentsDisplay(result2);
EnchantUtils.updateDisplay(result2);
e.setResult(result2);
this.plugin.runTask(c -> e.getInventory().setRepairCost(chargeables.size()), false);
this.plugin.runTask(task -> e.getInventory().setRepairCost(chargeables.size()));
return true;
}
private boolean handleEnchantMerging(@NotNull PrepareAnvilEvent e,
@NotNull ItemStack first, @NotNull ItemStack second, @NotNull ItemStack result) {
// Validate items in the first two slots.
if (second.getType().isAir() || second.getAmount() > 1 || !EnchantManager.isEnchantable(second)) return false;
if (second.getType().isAir() || second.getAmount() > 1 || !EnchantUtils.isEnchantable(second)) return false;
if (first.getType() == Material.ENCHANTED_BOOK && second.getType() != first.getType()) return false;
ItemStack result2 = new ItemStack(result.getType().isAir() ? first : result);
Map<ExcellentEnchant, Integer> enchantments = EnchantManager.getExcellentEnchantments(first);
Map<ExcellentEnchant, Integer> enchantments = EnchantUtils.getExcellents(first);
Map<ExcellentEnchant, Integer> charges = new HashMap<>(enchantments.keySet().stream().collect(Collectors.toMap(k -> k, v -> v.getCharges(first))));
AtomicInteger repairCost = new AtomicInteger(e.getInventory().getRepairCost());
// Merge only if it's Item + Item, Item + Enchanted book or Enchanted Book + Enchanted Book
if (second.getType() == Material.ENCHANTED_BOOK || second.getType() == first.getType()) {
EnchantManager.getExcellentEnchantments(second).forEach((enchant, level) -> {
EnchantUtils.getExcellents(second).forEach((enchant, level) -> {
enchantments.merge(enchant, level, (oldLvl, newLvl) -> (oldLvl.equals(newLvl)) ? (Math.min(enchant.getMaxLevel(), oldLvl + 1)) : (Math.max(oldLvl, newLvl)));
charges.merge(enchant, enchant.getCharges(second), Integer::sum);
});
@ -114,19 +114,19 @@ public class EnchantAnvilListener extends AbstractListener<ExcellentEnchants> {
// Recalculate operation cost depends on enchantments merge cost.
enchantments.forEach((enchant, level) -> {
if (EnchantManager.addEnchantment(result2, enchant, level, false)) {
if (EnchantUtils.add(result2, enchant, level, false)) {
repairCost.addAndGet(enchant.getAnvilMergeCost(level));
EnchantManager.setEnchantmentCharges(result2, enchant, charges.getOrDefault(enchant, 0));
EnchantUtils.setCharges(result2, enchant, charges.getOrDefault(enchant, 0));
}
});
if (first.equals(result2)) return false;
EnchantManager.updateEnchantmentsDisplay(result2);
EnchantUtils.updateDisplay(result2);
e.setResult(result2);
// NMS ContainerAnvil will set level cost to 0 right after calling the event, need 1 tick delay.
this.plugin.runTask((c) -> e.getInventory().setRepairCost(repairCost.get()), false);
this.plugin.runTask(task -> e.getInventory().setRepairCost(repairCost.get()));
return true;
}

View File

@ -21,10 +21,13 @@ import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.manager.AbstractListener;
import su.nexmedia.engine.hooks.Hooks;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import su.nightexpress.excellentenchants.hook.HookId;
import su.nightexpress.excellentenchants.hook.impl.MythicMobsHook;
import java.util.HashMap;
import java.util.Map;
@ -65,13 +68,13 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
ItemStack source = inventory.getItem(slot);
if (source == null || source.getType().isAir()) continue;
curses.putAll(EnchantManager.getExcellentEnchantments(source));
curses.putAll(EnchantUtils.getExcellents(source));
}
curses.entrySet().removeIf(entry -> !entry.getKey().isCursed());
curses.forEach((excellentEnchant, level) -> {
EnchantManager.addEnchantment(result, excellentEnchant, level, true);
EnchantUtils.add(result, excellentEnchant, level, true);
});
EnchantManager.updateEnchantmentsDisplay(result);
EnchantUtils.updateDisplay(result);
});
}
@ -81,7 +84,7 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
Item item = e.getItem();
ItemStack itemStack = item.getItemStack();
if (EnchantManager.updateEnchantmentsDisplay(itemStack)) {
if (EnchantUtils.updateDisplay(itemStack)) {
item.setItemStack(itemStack);
}
}
@ -93,7 +96,7 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
public void onEnchantPopulateEnchantingTable(final EnchantItemEvent e) {
ItemStack target = e.getItem();
Map<Enchantment, Integer> enchantsPrepared = e.getEnchantsToAdd();
Map<Enchantment, Integer> enchantsToPopulate = EnchantManager.getEnchantsToPopulate(target, ObtainType.ENCHANTING, enchantsPrepared, enchant -> enchant.getLevelByEnchantCost(e.getExpLevelCost()));
Map<Enchantment, Integer> enchantsToPopulate = EnchantUtils.getPopulationCandidates(target, ObtainType.ENCHANTING, enchantsPrepared, enchant -> enchant.getLevelByEnchantCost(e.getExpLevelCost()));
enchantsPrepared.putAll(enchantsToPopulate);
@ -116,10 +119,10 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
e.getEnchantsToAdd().forEach((enchantment, level) -> {
if (enchantment instanceof ExcellentEnchant enchant && enchant.isChargesEnabled()) {
EnchantManager.restoreEnchantmentCharges(result, enchant);
EnchantUtils.restoreCharges(result, enchant);
}
});
EnchantManager.updateEnchantmentsDisplay(result);
EnchantUtils.updateDisplay(result);
e.getInventory().setItem(0, result);
});
@ -133,8 +136,8 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
MerchantRecipe recipe = e.getRecipe();
ItemStack result = recipe.getResult();
if (!EnchantManager.isEnchantable(result)) return;
if (!EnchantManager.populateEnchantments(result, ObtainType.VILLAGER)) return;
if (!EnchantUtils.isEnchantable(result)) return;
if (!EnchantUtils.populate(result, ObtainType.VILLAGER)) return;
int uses = recipe.getUses();
int maxUses = recipe.getMaxUses();
@ -156,8 +159,8 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
if (entity instanceof Minecart || holder instanceof Chest) {
e.getLoot().forEach(item -> {
if (item != null && EnchantManager.isEnchantable(item)) {
EnchantManager.populateEnchantments(item, ObtainType.LOOT_GENERATION);
if (item != null && EnchantUtils.isEnchantable(item)) {
EnchantUtils.populate(item, ObtainType.LOOT_GENERATION);
}
});
}
@ -170,8 +173,8 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
if (!(e.getCaught() instanceof Item item)) return;
ItemStack itemStack = item.getItemStack();
if (EnchantManager.isEnchantable(itemStack)) {
EnchantManager.populateEnchantments(itemStack, ObtainType.FISHING);
if (EnchantUtils.isEnchantable(itemStack)) {
EnchantUtils.populate(itemStack, ObtainType.FISHING);
}
}
@ -185,14 +188,14 @@ public class EnchantGenericListener extends AbstractListener<ExcellentEnchants>
EntityEquipment equipment = entity.getEquipment();
if (equipment == null) return;
boolean isMythic = Hooks.isMythicMob(entity);
boolean isMythic = Hooks.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 (EnchantManager.isEnchantable(item)) {
if (doPopulation) EnchantManager.populateEnchantments(item, ObtainType.MOB_SPAWNING);
EnchantManager.getExcellentEnchantments(item).keySet().forEach(enchant -> EnchantManager.restoreEnchantmentCharges(item, enchant));
if (EnchantUtils.isEnchantable(item)) {
if (doPopulation) EnchantUtils.populate(item, ObtainType.MOB_SPAWNING);
EnchantUtils.getExcellents(item).keySet().forEach(enchant -> EnchantUtils.restoreCharges(item, enchant));
equipment.setItem(slot, item);
}
}

View File

@ -24,10 +24,11 @@ import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.api.manager.AbstractListener;
import su.nexmedia.engine.utils.EntityUtil;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.api.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.enchantment.util.EnchantDropContainer;
import su.nightexpress.excellentenchants.api.enchantment.type.*;
import su.nightexpress.excellentenchants.api.enchantment.meta.Arrowed;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants> {
@ -89,7 +90,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
ItemStack weapon = equipment.getItemInMainHand();
if (weapon.getType().isAir() || weapon.getType() == Material.ENCHANTED_BOOK) return;
EnchantManager.getExcellentEnchantments(weapon, CombatEnchant.class).forEach((combatEnchant, level) -> {
EnchantUtils.getExcellents(weapon, CombatEnchant.class).forEach((combatEnchant, level) -> {
if (combatEnchant.isOutOfCharges(weapon)) return;
if (combatEnchant.onAttack(e, damager, victim, weapon, level)) {
combatEnchant.consumeCharges(weapon);
@ -107,7 +108,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
for (ItemStack armor : EntityUtil.getEquippedArmor(victim).values()) {
if (armor == null || armor.getType().isAir()) continue;
EnchantManager.getExcellentEnchantments(armor, CombatEnchant.class).forEach((combatEnchant, level) -> {
EnchantUtils.getExcellents(armor, CombatEnchant.class).forEach((combatEnchant, level) -> {
if (combatEnchant.isOutOfCharges(armor)) return;
if (combatEnchant.onProtect(e, damager, victim, weaponDamager, level)) {
combatEnchant.consumeCharges(armor);
@ -117,7 +118,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
}
private void handleArmorEnchants(@NotNull EntityDamageEvent e, @NotNull LivingEntity entity) {
EnchantManager.getEquippedEnchants(entity, DamageEnchant.class).forEach((item, enchants) -> {
EnchantUtils.getEquipped(entity, DamageEnchant.class).forEach((item, enchants) -> {
enchants.forEach((enchant, level) -> {
if (enchant.isOutOfCharges(item)) return;
if (enchant.onDamage(e, entity, item, level)) {
@ -134,7 +135,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
ItemStack bow = this.getSourceWeapon(projectile);
if (bow == null || bow.getType().isAir() || bow.getType() == Material.ENCHANTED_BOOK) return;
EnchantManager.getExcellentEnchantments(bow, BowEnchant.class).forEach((bowEnchant, level) -> {
EnchantUtils.getExcellents(bow, BowEnchant.class).forEach((bowEnchant, level) -> {
bowEnchant.onDamage(e, projectile, shooter, victim, bow, level);
});
}
@ -150,7 +151,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
ItemStack bow = e.getBow();
if (bow == null || bow.getType().isAir() || bow.getType() == Material.ENCHANTED_BOOK) return;
EnchantManager.getExcellentEnchantments(bow, BowEnchant.class).forEach((bowEnchant, level) -> {
EnchantUtils.getExcellents(bow, BowEnchant.class).forEach((bowEnchant, level) -> {
if (bowEnchant.isOutOfCharges(bow)) return;
if (bowEnchant.onShoot(e, shooter, bow, level)) {
if (bowEnchant instanceof Arrowed arrowed && e.getProjectile() instanceof Projectile projectile) {
@ -176,7 +177,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
ItemStack bow = this.getSourceWeapon(projectile);
if (bow == null || bow.getType().isAir() || bow.getType() == Material.ENCHANTED_BOOK) return;
EnchantManager.getExcellentEnchantments(bow, BowEnchant.class).forEach((bowEnchant, level) -> {
EnchantUtils.getExcellents(bow, BowEnchant.class).forEach((bowEnchant, level) -> {
bowEnchant.onHit(e, projectile, bow, level);
});
@ -196,7 +197,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
if (item == null || item.getType().isAir() || item.getType() == Material.ENCHANTED_BOOK) return;
Player player = e.getPlayer();
EnchantManager.getExcellentEnchantments(item, InteractEnchant.class).forEach((interEnchant, level) -> {
EnchantUtils.getExcellents(item, InteractEnchant.class).forEach((interEnchant, level) -> {
if (interEnchant.isOutOfCharges(item)) return;
if (interEnchant.onInteract(e, player, item, level)) {
interEnchant.consumeCharges(item);
@ -211,7 +212,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
public void onEnchantDeath(EntityDeathEvent e) {
LivingEntity entity = e.getEntity();
EnchantManager.getEquippedEnchants(entity, DeathEnchant.class).forEach((item, enchants) -> {
EnchantUtils.getEquipped(entity, DeathEnchant.class).forEach((item, enchants) -> {
enchants.forEach(((deathEnchant, level) -> {
if (deathEnchant.isOutOfCharges(item)) return;
if (deathEnchant.onDeath(e, entity, level)) {
@ -226,7 +227,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
ItemStack weapon = killer.getInventory().getItemInMainHand();
if (weapon.getType().isAir() || weapon.getType() == Material.ENCHANTED_BOOK) return;
EnchantManager.getExcellentEnchantments(weapon, DeathEnchant.class).forEach((deathEnchant, level) -> {
EnchantUtils.getExcellents(weapon, DeathEnchant.class).forEach((deathEnchant, level) -> {
if (deathEnchant.isOutOfCharges(weapon)) return;
if (deathEnchant.onKill(e, entity, killer, level)) {
deathEnchant.consumeCharges(weapon);
@ -243,7 +244,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
ItemStack tool = player.getInventory().getItemInMainHand();
if (tool.getType().isAir() || tool.getType() == Material.ENCHANTED_BOOK) return;
EnchantManager.getExcellentEnchantments(tool, BlockBreakEnchant.class).forEach((blockEnchant, level) -> {
EnchantUtils.getExcellents(tool, BlockBreakEnchant.class).forEach((blockEnchant, level) -> {
if (blockEnchant.isOutOfCharges(tool)) return;
if (blockEnchant.onBreak(e, player, tool, level)) {
blockEnchant.consumeCharges(tool);
@ -260,7 +261,7 @@ public class EnchantHandlerListener extends AbstractListener<ExcellentEnchants>
if (tool.getType().isAir() || tool.getType() == Material.ENCHANTED_BOOK) return;
EnchantDropContainer dropContainer = new EnchantDropContainer(e);
EnchantManager.getExcellentEnchantments(tool, BlockDropEnchant.class).forEach((enchant, level) -> {
EnchantUtils.getExcellents(tool, BlockDropEnchant.class).forEach((enchant, level) -> {
if (enchant.isOutOfCharges(tool)) return;
if (enchant.onDrop(e, dropContainer, player, tool, level)) {
enchant.consumeCharges(tool);

View File

@ -3,15 +3,17 @@ package su.nightexpress.excellentenchants.enchantment.menu;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.config.JYML;
import su.nexmedia.engine.api.menu.AbstractMenuAuto;
import su.nexmedia.engine.api.menu.MenuClick;
import su.nexmedia.engine.api.menu.MenuItem;
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.lang.LangManager;
import su.nexmedia.engine.utils.Colorizer;
import su.nexmedia.engine.utils.ItemUtil;
@ -19,12 +21,12 @@ 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.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.EnchantRegister;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import java.util.*;
public class EnchantmentsListMenu extends AbstractMenuAuto<ExcellentEnchants, ExcellentEnchant> {
public class EnchantmentsListMenu extends ConfigMenu<ExcellentEnchants> implements AutoPaged<ExcellentEnchant> {
private static final String PATH = "/menu/enchants_list.yml";
@ -42,7 +44,7 @@ public class EnchantmentsListMenu extends AbstractMenuAuto<ExcellentEnchants, Ex
private final Map<String, Map<Integer, ItemStack>> iconCache;
public EnchantmentsListMenu(@NotNull ExcellentEnchants plugin) {
super(plugin, JYML.loadOrExtract(plugin, PATH), "");
super(plugin, JYML.loadOrExtract(plugin, PATH));
this.keyLevel = new NamespacedKey(plugin, "list_display_level");
this.iconCache = new HashMap<>();
@ -52,20 +54,12 @@ public class EnchantmentsListMenu extends AbstractMenuAuto<ExcellentEnchants, Ex
this.enchantLoreObtaining = Colorizer.apply(cfg.getStringList("Enchantments.Lore.Obtaining"));
this.enchantSlots = cfg.getIntArray("Enchantments.Slots");
MenuClick click = (player, type, e) -> {
if (type instanceof MenuItemType type2) {
this.onItemClickDefault(player, type2);
}
};
this.registerHandler(MenuItemType.class)
.addClick(MenuItemType.CLOSE, (viewer, event) -> plugin.runTask(task -> viewer.getPlayer().closeInventory()))
.addClick(MenuItemType.PAGE_NEXT, ClickHandler.forNextPage(this))
.addClick(MenuItemType.PAGE_PREVIOUS, ClickHandler.forPreviousPage(this));
for (String sId : cfg.getSection("Content")) {
MenuItem menuItem = cfg.getMenuItem("Content." + sId);
if (menuItem.getType() != null) {
menuItem.setClickHandler(click);
}
this.addItem(menuItem);
}
this.load();
}
@Override
@ -75,30 +69,42 @@ public class EnchantmentsListMenu extends AbstractMenuAuto<ExcellentEnchants, Ex
}
@Override
protected int[] getObjectSlots() {
public void onPrepare(@NotNull MenuViewer viewer, @NotNull MenuOptions options) {
super.onPrepare(viewer, options);
this.getItemsForPage(viewer).forEach(this::addItem);
}
@Override
public int[] getObjectSlots() {
return this.enchantSlots;
}
@Override
@NotNull
protected List<ExcellentEnchant> getObjects(@NotNull Player player) {
return new ArrayList<>(EnchantRegister.ENCHANT_REGISTRY.values().stream()
public Comparator<ExcellentEnchant> getObjectSorter() {
return (o1, o2) -> 0;
}
@Override
@NotNull
public List<ExcellentEnchant> getObjects(@NotNull Player player) {
return new ArrayList<>(EnchantRegistry.getRegistered().stream()
.sorted(Comparator.comparing(ExcellentEnchant::getName)).toList());
}
@Override
@NotNull
protected ItemStack getObjectStack(@NotNull Player player, @NotNull ExcellentEnchant enchant) {
public ItemStack getObjectStack(@NotNull Player player, @NotNull ExcellentEnchant enchant) {
return this.getEnchantIcon(enchant, 1);
}
@Override
@NotNull
protected MenuClick getObjectClick(@NotNull Player player, @NotNull ExcellentEnchant enchant) {
return (player1, type, e) -> {
if (!e.isLeftClick()) return;
public ItemClick getObjectClick(@NotNull ExcellentEnchant enchant) {
return (viewer, event) -> {
if (!event.isLeftClick()) return;
ItemStack itemClick = e.getCurrentItem();
ItemStack itemClick = event.getCurrentItem();
if (itemClick == null) return;
int levelHas = PDCUtil.getInt(itemClick, this.keyLevel).orElse(0);
@ -108,7 +114,7 @@ public class EnchantmentsListMenu extends AbstractMenuAuto<ExcellentEnchants, Ex
itemClick = this.getEnchantIcon(enchant, levelHas);
PDCUtil.set(itemClick, this.keyLevel, levelHas);
e.setCurrentItem(itemClick);
event.setCurrentItem(itemClick);
};
}
@ -143,9 +149,4 @@ public class EnchantmentsListMenu extends AbstractMenuAuto<ExcellentEnchants, Ex
ItemUtil.replace(icon, enchant.replaceAllPlaceholders(level));
return icon;
}
@Override
public boolean cancelClick(@NotNull InventoryClickEvent e, @NotNull SlotType slotType) {
return true;
}
}

View File

@ -2,7 +2,7 @@ package su.nightexpress.excellentenchants.enchantment.task;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.task.AbstractTask;
import su.nexmedia.engine.api.server.AbstractTask;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.config.Config;

View File

@ -1,11 +1,9 @@
package su.nightexpress.excellentenchants.enchantment.task;
import org.bukkit.Particle;
import org.bukkit.entity.Projectile;
import org.jetbrains.annotations.NotNull;
import su.nexmedia.engine.api.task.AbstractTask;
import su.nexmedia.engine.utils.EffectUtil;
import su.nexmedia.engine.utils.Pair;
import su.nexmedia.engine.api.particle.SimpleParticle;
import su.nexmedia.engine.api.server.AbstractTask;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.config.Config;
@ -16,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class ArrowTrailsTask extends AbstractTask<ExcellentEnchants> {
private static final Map<Projectile, Set<Pair<Particle, String>>> TRAILS_MAP = new ConcurrentHashMap<>();
private static final Map<Projectile, Set<SimpleParticle>> TRAILS_MAP = new ConcurrentHashMap<>();
public ArrowTrailsTask(@NotNull ExcellentEnchants plugin) {
super(plugin, Config.TASKS_ARROW_TRAIL_TICKS_INTERVAL.get(), true);
@ -29,17 +27,12 @@ public class ArrowTrailsTask extends AbstractTask<ExcellentEnchants> {
TRAILS_MAP.forEach((arrow, effects) -> {
effects.forEach(entry -> {
EffectUtil.playEffect(arrow.getLocation(), entry.getFirst(), entry.getSecond(), 0f, 0f, 0f, 0f, 10);
entry.play(arrow.getLocation(), 0f, 0f, 10);
});
});
}
@Deprecated
public static void add(@NotNull Projectile projectile, @NotNull String particleName, @NotNull String particleData) {
TRAILS_MAP.computeIfAbsent(projectile, list -> new HashSet<>()).add(Pair.of(Particle.valueOf(particleName), particleData));
}
public static void add(@NotNull Projectile projectile, @NotNull Particle particle, @NotNull String data) {
TRAILS_MAP.computeIfAbsent(projectile, list -> new HashSet<>()).add(Pair.of(particle, data));
public static void add(@NotNull Projectile projectile, @NotNull SimpleParticle particle) {
TRAILS_MAP.computeIfAbsent(projectile, list -> new HashSet<>()).add(particle);
}
}

View File

@ -4,7 +4,7 @@ import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.excellentenchants.ExcellentEnchants;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
public class PotionEffectsTask extends AbstractEnchantmentTask {
@ -15,7 +15,7 @@ public class PotionEffectsTask extends AbstractEnchantmentTask {
@Override
public void action() {
for (LivingEntity entity : this.getEntities()) {
EnchantManager.updateEquippedEnchantEffects(entity);
EnchantUtils.updateEquippedEffects(entity);
}
}
}

View File

@ -1,4 +1,4 @@
package su.nightexpress.excellentenchants.api.enchantment.util;
package su.nightexpress.excellentenchants.enchantment.util;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.inventory.ItemStack;

View File

@ -1,4 +1,4 @@
package su.nightexpress.excellentenchants.api.enchantment.util;
package su.nightexpress.excellentenchants.enchantment.util;
public enum EnchantPriority {

View File

@ -0,0 +1,359 @@
package su.nightexpress.excellentenchants.enchantment.util;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.entity.LivingEntity;
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.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.utils.CollectionsUtil;
import su.nexmedia.engine.utils.EntityUtil;
import su.nexmedia.engine.utils.ItemUtil;
import su.nexmedia.engine.utils.PDCUtil;
import su.nexmedia.engine.utils.random.Rnd;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.IEnchantment;
import su.nightexpress.excellentenchants.api.enchantment.meta.Potioned;
import su.nightexpress.excellentenchants.api.enchantment.type.PassiveEnchant;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.config.ObtainSettings;
import su.nightexpress.excellentenchants.enchantment.EnchantPopulator;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import su.nightexpress.excellentenchants.tier.Tier;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class EnchantUtils {
public static final NamespacedKey KEY_LORE_SIZE = new NamespacedKey(ExcellentEnchantsAPI.PLUGIN, "lore_size");
public static boolean isEnchantable(@NotNull ItemStack item) {
if (item.getType().isAir()) return false;
return item.getType() == Material.ENCHANTED_BOOK || Stream.of(EnchantmentTarget.values()).anyMatch(target -> target.includes(item));
}
public static boolean populate(@NotNull ItemStack item, @NotNull ObtainType obtainType) {
int enchantsHad = getAmount(item);
getPopulationCandidates(item, obtainType).forEach((enchantment, level) -> {
add(item, enchantment, level, false);
});
updateDisplay(item);
return getAmount(item) != enchantsHad;
}
@NotNull
public static Set<ExcellentEnchant> populateFilter(@NotNull Set<ExcellentEnchant> enchants,
@NotNull ObtainType obtainType, @Nullable ItemStack item) {
Set<ExcellentEnchant> set = enchants.stream()
.filter(enchant -> enchant.getObtainChance(obtainType) > 0)
.filter(enchant -> item == null || enchant.canEnchantItem(item))
.collect(Collectors.toCollection(HashSet::new));
set.removeIf(enchant -> obtainType == ObtainType.ENCHANTING && (enchant.isTreasure() || enchant.isCursed()));
return set;
}
@NotNull
public static Map<Enchantment, Integer> getPopulationCandidates(@NotNull ItemStack item, @NotNull ObtainType obtainType) {
return getPopulationCandidates(item, obtainType, new HashMap<>(), (enchant) -> enchant.generateLevel(obtainType));
}
@NotNull
public static Map<Enchantment, Integer> getPopulationCandidates(@NotNull ItemStack item, @NotNull ObtainType obtainType,
@NotNull Map<Enchantment, Integer> enchantsPrepared,
@NotNull Function<ExcellentEnchant, Integer> levelFunc) {
Map<Enchantment, Integer> enchantsToAdd = new HashMap<>(enchantsPrepared);
ObtainSettings settings = Config.getObtainSettings(obtainType).orElse(null);
if (settings == null || !Rnd.chance(settings.getEnchantsCustomGenerationChance())) return enchantsToAdd;
int enchMax = settings.getEnchantsTotalMax();
int enchRoll = Rnd.get(settings.getEnchantsCustomMin(), settings.getEnchantsCustomMax());
// Класс для исключения неудачных попыток.
EnchantPopulator populator = new EnchantPopulator(obtainType, item);
// Добавляем сколько можем, пока нужное количество не будет добавлено или не закончатся чары и/или тиры.
while (!populator.isEmpty() && enchRoll > 0) {
// Достигнут максимум чар (любых) для итема, заканчиваем.
if (enchantsToAdd.size() >= enchMax) break;
Tier tier = populator.getTierByChance();
if (tier == null) break; // Нет тира?
ExcellentEnchant enchant = populator.getEnchantByChance(tier);
// В тире нет подходящих чар (вообще) для итема, исключаем и идем дальше.
if (enchant == null) {
populator.getEnchants().remove(tier);
continue;
}
// Среди уже добавленных чар есть конфликты с тем, что нашли.
// Исключаем, идем дальше.
if (enchantsToAdd.keySet().stream().anyMatch(has -> has.conflictsWith(enchant) || enchant.conflictsWith(has))) {
populator.getEnchants(tier).remove(enchant);
continue;
}
// Не получилось сгенерировать подходящий уровень.
// Исключаем, идем дальше.
int level = levelFunc.apply(enchant);
if (level < enchant.getStartLevel()) {
populator.getEnchants(tier).remove(enchant);
continue;
}
// Добавляем чар, засчитываем попытку.
populator.getEnchants(tier).remove(enchant);
enchantsToAdd.put(enchant, level);
enchRoll--;
}
return enchantsToAdd;
}
public static boolean add(@NotNull ItemStack item, @NotNull Enchantment enchantment, int level, boolean force) {
if (!force && !enchantment.canEnchantItem(item)) return false;
remove(item, enchantment);
ItemMeta meta = item.getItemMeta();
if (meta == null) return false;
if (meta instanceof EnchantmentStorageMeta storageMeta) {
if (!storageMeta.addStoredEnchant(enchantment, level, true)) return false;
}
else {
if (!meta.addEnchant(enchantment, level, true)) return false;
}
item.setItemMeta(meta);
return true;
}
public static void remove(@NotNull ItemStack item, @NotNull Enchantment enchantment) {
ItemMeta meta = item.getItemMeta();
if (meta instanceof EnchantmentStorageMeta storageMeta) {
storageMeta.removeStoredEnchant(enchantment);
}
else {
meta.removeEnchant(enchantment);
}
item.setItemMeta(meta);
}
public static boolean updateDisplay(@NotNull ItemStack item) {
if (Config.ENCHANTMENTS_DISPLAY_MODE.get() != 1) return false;
if (!isEnchantable(item)) {
PDCUtil.remove(item, KEY_LORE_SIZE);
return false;
}
Map<ExcellentEnchant, Integer> enchants = getExcellents(item);
int sizeHas = PDCUtil.getInt(item, KEY_LORE_SIZE).orElse(0);
int sizeReal = enchants.size();
ItemMeta meta = item.getItemMeta();
if (meta == null) return false;
List<String> lore = meta.getLore() == null ? new ArrayList<>() : meta.getLore();
for (int index = 0; index < sizeHas && !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 (Config.ENCHANTMENTS_DESCRIPTION_ENABLED.get()) {
enchants.forEach((enchant, level) -> {
lore.addAll(0, enchant.formatDescription(level));
});
sizeReal += enchants.keySet().stream().map(ExcellentEnchant::getDescription).mapToInt(List::size).sum();
}
enchants.forEach((enchant, level) -> {
lore.add(0, enchant.getNameFormatted(level, getCharges(meta, enchant)));
});
}
else sizeReal = 0;
meta.setLore(lore);
if (sizeReal > 0) {
PDCUtil.set(meta, KEY_LORE_SIZE, sizeReal);
}
item.setItemMeta(meta);
return true;
}
@NotNull
public static Map<Enchantment, Integer> getAll(@NotNull ItemStack item) {
ItemMeta meta = item.getItemMeta();
return meta == null ? Collections.emptyMap() : getAll(meta);
}
@NotNull
public static Map<Enchantment, Integer> 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 boolean contains(@NotNull ItemStack item, @NotNull Enchantment enchantment) {
return getLevel(item, enchantment) > 0;
}
public static int getLevel(@NotNull ItemStack item, @NotNull Enchantment enchant) {
return getAll(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 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);
int max = enchant.getChargesMax(level);
return getCharges(item, enchant) == max;
}
public static void consumeCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return;
int level = getLevel(item, enchant);
int has = getCharges(item, enchant);
int use = enchant.getChargesConsumeAmount(level);
setCharges(item, enchant, has - use);
}
public static void restoreCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return;
int level = getLevel(item, enchant);
int max = enchant.getChargesMax(level);
setCharges(item, enchant, max);
}
public static void rechargeCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant) {
if (!enchant.isChargesEnabled()) return;
int level = getLevel(item, enchant);
int recharge = enchant.getChargesRechargeAmount(level);
int has = getCharges(item, enchant);
setCharges(item, enchant, has + recharge);
}
public static void setCharges(@NotNull ItemStack item, @NotNull ExcellentEnchant enchant, int charges) {
if (!enchant.isChargesEnabled()) return;
int level = getLevel(item, enchant);
int max = enchant.getChargesMax(level);
PDCUtil.set(item, enchant.getChargesKey(), Math.max(0, Math.min(charges, max)));
}
public static int getExcellentAmount(@NotNull ItemStack item) {
return getExcellents(item).size();
}
@NotNull
public static Map<ExcellentEnchant, Integer> getExcellents(@NotNull ItemStack item) {
return getExcellents(getAll(item));
}
@NotNull
public static Map<ExcellentEnchant, Integer> getExcellents(@NotNull ItemMeta meta) {
return getExcellents(getAll(meta));
}
@NotNull
private static Map<ExcellentEnchant, Integer> getExcellents(@NotNull Map<Enchantment, Integer> enchants) {
Map<ExcellentEnchant, Integer> map = new HashMap<>();
enchants.forEach((enchantment, level) -> {
ExcellentEnchant excellent = EnchantRegistry.get(enchantment.getKey());
if (excellent != null) {
map.put(excellent, level);
}
});
return map;
}
@NotNull
public static <T extends IEnchantment> Map<T, Integer> getExcellents(@NotNull ItemStack item, @NotNull Class<T> clazz) {
Map<T, Integer> map = new HashMap<>();
getAll(item).forEach((enchantment, level) -> {
ExcellentEnchant excellent = EnchantRegistry.get(enchantment.getKey());
if (excellent == null || !clazz.isAssignableFrom(excellent.getClass())) return;
map.put(clazz.cast(excellent), level);
});
return CollectionsUtil.sort(map, Comparator.comparing(p -> p.getKey().getPriority(), Comparator.reverseOrder()));
}
@NotNull
public static Map<EquipmentSlot, ItemStack> getEnchantedEquipment(@NotNull LivingEntity entity) {
Map<EquipmentSlot, ItemStack> equipment = EntityUtil.getEquippedItems(entity);
equipment.entrySet().removeIf(entry -> {
ItemStack item = entry.getValue();
EquipmentSlot slot = entry.getKey();
if (item == null || item.getType().isAir() || item.getType() == Material.ENCHANTED_BOOK) return true;
if ((slot == EquipmentSlot.HAND || slot == EquipmentSlot.OFF_HAND) && ItemUtil.isArmor(item)) return true;
return !item.hasItemMeta();
});
return equipment;
}
@NotNull
public static Map<ItemStack, Map<ExcellentEnchant, Integer>> getEquipped(@NotNull LivingEntity entity) {
Map<ItemStack, Map<ExcellentEnchant, Integer>> map = new HashMap<>();
getEnchantedEquipment(entity).values().forEach(item -> {
map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getExcellents(item));
});
return map;
}
@NotNull
public static <T extends IEnchantment> Map<ItemStack, Map<T, Integer>> getEquipped(@NotNull LivingEntity entity,
@NotNull Class<T> clazz) {
Map<ItemStack, Map<T, Integer>> map = new HashMap<>();
getEnchantedEquipment(entity).values().forEach(item -> {
map.computeIfAbsent(item, k -> new LinkedHashMap<>()).putAll(getExcellents(item, clazz));
});
return map;
}
public static void updateEquippedEffects(@NotNull LivingEntity entity) {
getEquipped(entity, PassiveEnchant.class).forEach((item, enchants) -> {
enchants.forEach((enchant, level) -> {
if (enchant instanceof Potioned potioned) {
if (enchant.isOutOfCharges(item)) return;
if (enchant.onTrigger(entity, item, level)) {
enchant.consumeCharges(item);
}
}
});
});
}
}

View File

@ -2,6 +2,7 @@ package su.nightexpress.excellentenchants.hook;
public class HookId {
public static final String MYTHIC_MOBS = "MythicMobs";
public static final String NCP = "NoCheatPlus";
public static final String PROTOCOL_LIB = "ProtocolLib";
}

View File

@ -0,0 +1,14 @@
package su.nightexpress.excellentenchants.hook.impl;
import io.lumine.mythic.bukkit.MythicBukkit;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
public class MythicMobsHook {
private static final MythicBukkit MYTHIC_MOBS = MythicBukkit.inst();
public static boolean isMythicMob(@NotNull Entity entity) {
return MYTHIC_MOBS.getAPIHelper().isMythicMob(entity);
}
}

View File

@ -9,8 +9,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.utils.StringUtil;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.EnchantRegister;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.EnchantRegistry;
public class PlaceholderHook {
@ -63,7 +63,7 @@ public class PlaceholderHook {
ItemStack item = player.getInventory().getItem(slot);
if (item == null || item.getType().isAir()) return "-";
ExcellentEnchant enchant = EnchantRegister.get(NamespacedKey.minecraft(chargesSplit[1].toLowerCase()));
ExcellentEnchant enchant = EnchantRegistry.get(NamespacedKey.minecraft(chargesSplit[1].toLowerCase()));
if (enchant == null) return null;
return String.valueOf(enchant.getCharges(item));
@ -72,7 +72,7 @@ public class PlaceholderHook {
String[] chargesSplit = params.substring("charges_maximum_".length()).split(":");
if (chargesSplit.length < 2) return null;
ExcellentEnchant enchant = EnchantRegister.get(NamespacedKey.minecraft(chargesSplit[0].toLowerCase()));
ExcellentEnchant enchant = EnchantRegistry.get(NamespacedKey.minecraft(chargesSplit[0].toLowerCase()));
if (enchant == null) return null;
int level = StringUtil.getInteger(chargesSplit[1], 1);

View File

@ -13,9 +13,9 @@ import org.bukkit.inventory.MerchantRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.Nullable;
import su.nightexpress.excellentenchants.ExcellentEnchantsAPI;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.impl.ExcellentEnchant;
import su.nightexpress.excellentenchants.config.Config;
import su.nightexpress.excellentenchants.enchantment.EnchantManager;
import su.nightexpress.excellentenchants.enchantment.util.EnchantUtils;
import java.util.*;
import java.util.stream.Collectors;
@ -85,7 +85,7 @@ public class ProtocolHook {
ItemMeta meta = copy.getItemMeta();
if (meta == null || meta.hasItemFlag(ItemFlag.HIDE_ENCHANTS)) return item;
Map<ExcellentEnchant, Integer> enchants = EnchantManager.getExcellentEnchantments(meta)
Map<ExcellentEnchant, Integer> enchants = EnchantUtils.getExcellents(meta)
.entrySet().stream()
.sorted(Comparator.comparing(e -> e.getKey().getTier().getPriority()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (old,nev) -> nev, LinkedHashMap::new));
@ -106,7 +106,7 @@ public class ProtocolHook {
});
}
enchants.forEach((enchant, level) -> {
int charges = EnchantManager.getEnchantmentCharges(meta, enchant);
int charges = EnchantUtils.getCharges(meta, enchant);
lore.add(0, enchant.getNameFormatted(level, charges));
});

View File

@ -1,38 +1,23 @@
package su.nightexpress.excellentenchants.tier;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import su.nexmedia.engine.api.manager.IPlaceholder;
import su.nexmedia.engine.api.placeholder.Placeholder;
import su.nexmedia.engine.api.placeholder.PlaceholderMap;
import su.nexmedia.engine.utils.Colorizer;
import su.nightexpress.excellentenchants.Placeholders;
import su.nightexpress.excellentenchants.api.enchantment.ExcellentEnchant;
import su.nightexpress.excellentenchants.enchantment.type.ObtainType;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Tier implements IPlaceholder {
public static final Tier DEFAULT = new Tier(Placeholders.DEFAULT, 100, "Default", ChatColor.WHITE, new HashMap<>());
static {
Stream.of(ObtainType.values()).forEach(type -> DEFAULT.getChance().put(type, 100D));
}
public class Tier implements Placeholder {
private final String id;
private final int priority;
private final String name;
private final ChatColor color;
private final Map<ObtainType, Double> chance;
private final Set<ExcellentEnchant> enchants;
private final PlaceholderMap placeholderMap;
public Tier(@NotNull String id, int priority, @NotNull String name, @NotNull ChatColor color,
@NotNull Map<ObtainType, Double> chance) {
@ -41,16 +26,16 @@ public class Tier implements IPlaceholder {
this.name = Colorizer.apply(name);
this.color = color;
this.chance = chance;
this.enchants = new HashSet<>();
this.placeholderMap = new PlaceholderMap()
.add(Placeholders.TIER_ID, this::getId)
.add(Placeholders.TIER_NAME, this::getName)
;
}
@Override
@NotNull
public UnaryOperator<String> replacePlaceholders() {
return str -> str
.replace(Placeholders.TIER_ID, this.getId())
.replace(Placeholders.TIER_NAME, this.getName())
;
public PlaceholderMap getPlaceholders() {
return this.placeholderMap;
}
@NotNull
@ -80,24 +65,4 @@ public class Tier implements IPlaceholder {
public double getChance(@NotNull ObtainType obtainType) {
return this.getChance().getOrDefault(obtainType, 0D);
}
@NotNull
public Set<ExcellentEnchant> getEnchants() {
return this.enchants;
}
@NotNull
public Set<ExcellentEnchant> getEnchants(@NotNull ObtainType obtainType) {
return this.getEnchants(obtainType, null);
}
@NotNull
public Set<ExcellentEnchant> getEnchants(@NotNull ObtainType obtainType, @Nullable ItemStack item) {
Set<ExcellentEnchant> set = this.getEnchants().stream()
.filter(enchant -> enchant.getObtainChance(obtainType) > 0)
.filter(enchant -> item == null || enchant.canEnchantItem(item))
.collect(Collectors.toCollection(HashSet::new));
set.removeIf(enchant -> obtainType == ObtainType.ENCHANTING && (enchant.isTreasure() || enchant.isCursed()));
return set;
}
}

View File

@ -14,6 +14,8 @@ import java.util.stream.Collectors;
public class TierManager extends AbstractManager<ExcellentEnchants> {
public static final String FILE_NAME = "tiers.yml";
private JYML config;
private final Map<String, Tier> tiers;
@ -30,7 +32,7 @@ public class TierManager extends AbstractManager<ExcellentEnchants> {
return;
}*/
this.config = JYML.loadOrExtract(plugin, "tiers.yml");
this.config = JYML.loadOrExtract(plugin, FILE_NAME);
for (String sId : config.getSection("")) {
String path = sId + ".";
@ -58,10 +60,6 @@ public class TierManager extends AbstractManager<ExcellentEnchants> {
this.tiers.put(tier.getId(), tier);
}
if (this.tiers.isEmpty()) {
this.tiers.put(Tier.DEFAULT.getId(), Tier.DEFAULT);
}
this.plugin.info("Tiers Loaded: " + this.tiers.size());
}
@ -93,6 +91,22 @@ public class TierManager extends AbstractManager<ExcellentEnchants> {
@Nullable
public Tier getTierByChance(@NotNull ObtainType obtainType) {
Map<Tier, Double> map = this.getTiers().stream().collect(Collectors.toMap(k -> k, v -> v.getChance(obtainType)));
return Rnd.get(map);
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());
}
}

Some files were not shown because too many files have changed in this diff Show More