Changed up the system a bit

This commit is contained in:
GB6 2019-01-19 14:54:00 +01:00
parent 5cc92b0bb3
commit e11bbf6a8d
30 changed files with 1079 additions and 129 deletions

View File

@ -46,14 +46,7 @@
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>co.aikar.commands</pattern>
<shadedPattern>com.songoda.epicenchants.acf</shadedPattern> <!-- Replace this -->
</relocation>
</relocations>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
</configuration>
<executions>
<execution>
@ -77,7 +70,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.8.8</version>
<version>1.13.2</version>
<scope>provided</scope>
</dependency>

View File

@ -3,16 +3,24 @@ package com.songoda.epicenchants;
import co.aikar.commands.BukkitCommandManager;
import co.aikar.commands.InvalidCommandArgument;
import com.songoda.epicenchants.commands.EnchantCommand;
import com.songoda.epicenchants.listeners.ArmorListener;
import com.songoda.epicenchants.listeners.BookListener;
import com.songoda.epicenchants.listeners.PlayerListener;
import com.songoda.epicenchants.managers.EnchantManager;
import com.songoda.epicenchants.managers.FileManager;
import com.songoda.epicenchants.objects.Enchant;
import com.songoda.epicenchants.utils.InventoryParser;
import com.songoda.epicenchants.utils.EnchantUtils;
import com.songoda.epicenchants.utils.VersionDependentList;
import com.songoda.epicenchants.utils.parser.InventoryParser;
import fr.minuskube.inv.InventoryManager;
import fr.minuskube.inv.SmartInventory;
import lombok.Getter;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.HashSet;
import java.util.stream.Collectors;
import static com.songoda.epicenchants.utils.Chat.color;
@ -27,6 +35,7 @@ public class EpicEnchants extends JavaPlugin {
@Getter private Economy economy;
@Getter private Locale locale;
@Getter private SmartInventory bookInventory;
@Getter private EnchantUtils enchantUtils;
@Override
public void onEnable() {
@ -37,14 +46,19 @@ public class EpicEnchants extends JavaPlugin {
this.fileManager = new FileManager(this);
this.enchantManager = new EnchantManager();
this.inventoryManager = new InventoryManager(this);
this.locale = Locale.getLocale(getConfig().getString("System.Language Mode", getConfig().getString("language")));
this.economy = getServer().getServicesManager().getRegistration(Economy.class).getProvider();
this.enchantUtils = new EnchantUtils(this);
Locale.init(this);
this.locale = Locale.getLocale(getConfig().getString("language"));
fileManager.createFiles();
fileManager.loadEnchants();
inventoryManager.init();
setupCommands();
setupListeners();
setupVersion();
if (!enchantManager.getEnchants().isEmpty()) {
getLogger().info("Successfully loaded: " + enchantManager.getEnchants().stream().map(Enchant::getIdentifier).collect(Collectors.joining(",")));
@ -72,4 +86,24 @@ public class EpicEnchants extends JavaPlugin {
commandManager.registerCommand(new EnchantCommand());
}
private void setupListeners() {
EpicEnchants instance = this;
new HashSet<Listener>() {{
add(new BookListener(instance));
add(new ArmorListener());
add(new PlayerListener(instance));
}}.forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, this));
}
private void setupVersion() {
int currentVersion = Integer.parseInt(getServer().getClass().getPackage().getName().split("\\.")[3].split("_")[1]);
if(currentVersion >= 13) {
VersionDependentList.initDefault();
} else {
VersionDependentList.initLegacy();
}
}
}

View File

@ -67,6 +67,7 @@ public class Locale {
localeFolder.mkdirs();
Locale.searchForLocales();
Locale.saveDefaultLocale("en_US");
}
/**
@ -259,6 +260,26 @@ public class Locale {
return ChatColor.translateAlternateColorCodes('&', this.getMessageOrDefault(node, node));
}
/**
* Get a message set for a specific node with prefix
*
* @param node the node to get
* @return the message for the specified node
*/
public String getMessageWithPrefix(String node) {
return ChatColor.translateAlternateColorCodes('&', getPrefix() + this.getMessageOrDefault(node, node));
}
/**
* Get a message set for a specific node with prefix
*
* @param node the node to get
* @return the message for the specified node
*/
public String getMessageWithPrefix(String node, Object... args) {
return ChatColor.translateAlternateColorCodes('&', getPrefix() + getMessage(node, args));
}
/**
* Get a message set for a specific node and replace its params with a supplied arguments.
*
@ -269,7 +290,7 @@ public class Locale {
public String getMessage(String node, Object... args) {
String message = getMessage(node);
for (Object arg : args) {
message = message.replaceFirst("%.*?%", arg.toString());
message = message.replaceFirst("\\{.*?}", arg.toString());
}
return message;
}

View File

@ -17,8 +17,8 @@ public class EnchantCommand extends BaseCommand {
@CommandCompletion("@players @enchants @nothing @nothing @nothing")
@Description("Give books to players")
@CommandPermission("epicenchants.givebook")
public void onGiveBook(@Flags("other") Player target, Enchant enchant, @Default("1") int tier, @Optional Double successRate, @Optional Double destroyRate) {
target.getInventory().addItem(enchant.getBookItem().get(enchant, tier, successRate, destroyRate));
public void onGiveBook(@Flags("other") Player target, Enchant enchant, @Optional Integer level, @Optional Integer successRate, @Optional Integer destroyRate) {
target.getInventory().addItem(enchant.getBookItem().get(enchant, level, successRate, destroyRate));
}
@Default

View File

@ -0,0 +1,5 @@
package com.songoda.epicenchants.enums;
public enum EnchantProcType {
DAMAGED, DEALT_DAMAGE, MINED
}

View File

@ -0,0 +1,5 @@
package com.songoda.epicenchants.enums;
public enum EnchantResult {
SUCCESS, FAILURE, BROKEN_FAILURE
}

View File

@ -0,0 +1,26 @@
package com.songoda.epicenchants.enums;
import org.bukkit.Material;
import java.util.Arrays;
public enum MaterialType {
TOOL("PICKAXE", "SHOVEL", "SPADE", "AXE", "HOE"),
WEAPON("SWORD", "BOW", "AXE"),
ARMOR("HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS");
private String[] types;
MaterialType(String... types) {
this.types = types;
}
public boolean is(Material material) {
return Arrays.stream(types).anyMatch(s -> material.toString().contains(s));
}
public static MaterialType of(String string) {
return Arrays.stream(values()).filter(s -> s.toString().equals(string.toUpperCase())).findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unknown MaterialType: " + string));
}
}

View File

@ -0,0 +1,169 @@
package com.songoda.epicenchants.events;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
public final class ArmorEquipEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;
private final EquipMethod equipType;
private final ArmorType type;
private ItemStack oldArmorPiece, newArmorPiece;
/**
* Constructor for the ArmorEquipEvent.
*
* @param player The player who put on / removed the armor.
* @param type The ArmorType of the armor added
* @param oldArmorPiece The ItemStack of the armor removed.
* @param newArmorPiece The ItemStack of the armor added.
*/
public ArmorEquipEvent(final Player player, final EquipMethod equipType, final ArmorType type, final ItemStack oldArmorPiece, final ItemStack newArmorPiece) {
super(player);
this.equipType = equipType;
this.type = type;
this.oldArmorPiece = oldArmorPiece;
this.newArmorPiece = newArmorPiece;
}
/**
* Gets a list of handlers handling this event.
*
* @return A list of handlers handling this event.
*/
public final static HandlerList getHandlerList() {
return handlers;
}
/**
* Gets a list of handlers handling this event.
*
* @return A list of handlers handling this event.
*/
@Override
public final HandlerList getHandlers() {
return handlers;
}
/**
* Sets if this event should be cancelled.
*
* @param cancel If this event should be cancelled.
*/
public final void setCancelled(final boolean cancel) {
this.cancel = cancel;
}
/**
* Gets if this event is cancelled.
*
* @return If this event is cancelled
*/
public final boolean isCancelled() {
return cancel;
}
public final ArmorType getType() {
return type;
}
/**
* Returns the last equipped armor piece, could be a piece of armor, {@link Material#AIR}, or null.
*/
public final ItemStack getOldArmorPiece() {
return oldArmorPiece;
}
public final void setOldArmorPiece(final ItemStack oldArmorPiece) {
this.oldArmorPiece = oldArmorPiece;
}
/**
* Returns the newly equipped armor, could be a piece of armor, {@link Material#AIR}, or null.
*/
public final ItemStack getNewArmorPiece() {
return newArmorPiece;
}
public final void setNewArmorPiece(final ItemStack newArmorPiece) {
this.newArmorPiece = newArmorPiece;
}
/**
* Gets the method used to either equip or unequip an armor piece.
*/
public EquipMethod getMethod() {
return equipType;
}
public enum EquipMethod {// These have got to be the worst documentations ever.
/**
* When you shift click an armor piece to equip or unequip
*/
SHIFT_CLICK,
/**
* When you drag and drop the item to equip or unequip
*/
DRAG,
/**
* When you manually equip or unequip the item. Use to be DRAG
*/
PICK_DROP,
/**
* When you right click an armor piece in the hotbar without the inventory open to equip.
*/
HOTBAR,
/**
* When you press the hotbar slot number while hovering over the armor slot to equip or unequip
*/
HOTBAR_SWAP,
/**
* When in range of a dispenser that shoots an armor piece to equip.
*/
DISPENSER,
/**
* When an armor piece is removed due to it losing all durability.
*/
BROKE,
/**
* When you die causing all armor to unequip
*/
DEATH,
;
}
public enum ArmorType {
HELMET(5), CHESTPLATE(6), LEGGINGS(7), BOOTS(8);
private final int slot;
ArmorType(int slot) {
this.slot = slot;
}
/**
* Attempts to match the ArmorType for the specified ItemStack.
*
* @param itemStack The ItemStack to parse the type of.
* @return The parsed ArmorType. (null if none were found.)
*/
public static ArmorType matchType(final ItemStack itemStack) {
if (itemStack == null || itemStack.getType().equals(Material.AIR)) return null;
String type = itemStack.getType().name();
if (type.endsWith("_HELMET") || type.endsWith("_SKULL")) return HELMET;
else if (type.endsWith("_CHESTPLATE")) return CHESTPLATE;
else if (type.endsWith("_LEGGINGS")) return LEGGINGS;
else if (type.endsWith("_BOOTS")) return BOOTS;
else return null;
}
public int getSlot() {
return slot;
}
}
}

View File

@ -0,0 +1,44 @@
package com.songoda.epicenchants.events;
import com.songoda.epicenchants.objects.Enchant;
import lombok.Getter;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
@Getter
public class EnchantApplyEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private ItemStack toEnchant;
private Enchant enchant;
private int level, successRate, destroyRate;
private boolean cancelled = false;
public EnchantApplyEvent(ItemStack toEnchant, Enchant enchant, int level, int successRate, int destroyRate) {
this.toEnchant = toEnchant;
this.enchant = enchant;
this.level = level;
this.successRate = successRate;
this.destroyRate = destroyRate;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}

View File

@ -0,0 +1,191 @@
package com.songoda.epicenchants.listeners;
import com.songoda.epicenchants.events.ArmorEquipEvent;
import com.songoda.epicenchants.events.ArmorEquipEvent.ArmorType;
import com.songoda.epicenchants.events.ArmorEquipEvent.EquipMethod;
import com.songoda.epicenchants.utils.VersionDependentList;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.*;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemBreakEvent;
import org.bukkit.inventory.ItemStack;
public class ArmorListener implements Listener {
@EventHandler
public final void onInventoryClick(final InventoryClickEvent e) {
boolean shift = false, numberkey = false;
if (e.isCancelled()) return;
if (e.getAction() == InventoryAction.NOTHING) return;// Why does this get called if nothing happens??
if (e.getClick().equals(ClickType.SHIFT_LEFT) || e.getClick().equals(ClickType.SHIFT_RIGHT)) {
shift = true;
}
if (e.getClick().equals(ClickType.NUMBER_KEY)) {
numberkey = true;
}
if (e.getSlotType() != SlotType.ARMOR && e.getSlotType() != SlotType.QUICKBAR && e.getSlotType() != SlotType.CONTAINER)
return;
if (e.getClickedInventory() != null && !e.getClickedInventory().getType().equals(InventoryType.PLAYER)) return;
if (!e.getInventory().getType().equals(InventoryType.CRAFTING) && !e.getInventory().getType().equals(InventoryType.PLAYER))
return;
if (!(e.getWhoClicked() instanceof Player)) return;
ArmorType newArmorType = ArmorType.matchType(shift ? e.getCurrentItem() : e.getCursor());
if (!shift && newArmorType != null && e.getRawSlot() != newArmorType.getSlot()) {
// Used for drag and drop checking to make sure you aren't trying to place a helmet in the boots slot.
return;
}
if (shift) {
newArmorType = ArmorType.matchType(e.getCurrentItem());
if (newArmorType != null) {
boolean equipping = true;
if (e.getRawSlot() == newArmorType.getSlot()) {
equipping = false;
}
if (newArmorType.equals(ArmorType.HELMET) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getHelmet())) || newArmorType.equals(ArmorType.CHESTPLATE) && (equipping ? isAirOrNull(e.getWhoClicked().getInventory().getChestplate()) : !isAirOrNull(e.getWhoClicked().getInventory().getChestplate())) || newArmorType.equals(ArmorType.LEGGINGS) && (equipping ? isAirOrNull(e.getWhoClicked().getInventory().getLeggings()) : !isAirOrNull(e.getWhoClicked().getInventory().getLeggings())) || newArmorType.equals(ArmorType.BOOTS) && (equipping ? isAirOrNull(e.getWhoClicked().getInventory().getBoots()) : !isAirOrNull(e.getWhoClicked().getInventory().getBoots()))) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), EquipMethod.SHIFT_CLICK, newArmorType, equipping ? null : e.getCurrentItem(), equipping ? e.getCurrentItem() : null);
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
}
}
}
} else {
ItemStack newArmorPiece = e.getCursor();
ItemStack oldArmorPiece = e.getCurrentItem();
if (numberkey) {
if (e.getClickedInventory().getType().equals(InventoryType.PLAYER)) {// Prevents shit in the 2by2 crafting
// e.getClickedInventory() == The players inventory
// e.getHotBarButton() == key people are pressing to equip or unequip the item to or from.
// e.getRawSlot() == The slot the item is going to.
// e.getSlot() == Armor slot, can't use e.getRawSlot() as that gives a hotbar slot ;-;
ItemStack hotbarItem = e.getClickedInventory().getItem(e.getHotbarButton());
if (!isAirOrNull(hotbarItem)) {// Equipping
newArmorType = ArmorType.matchType(hotbarItem);
newArmorPiece = hotbarItem;
oldArmorPiece = e.getClickedInventory().getItem(e.getSlot());
} else {// Unequipping
newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
}
}
} else {
if (isAirOrNull(e.getCursor()) && !isAirOrNull(e.getCurrentItem())) {// unequip with no new item going into the slot.
newArmorType = ArmorType.matchType(e.getCurrentItem());
}
// e.getCurrentItem() == Unequip
// e.getCursor() == Equip
// newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
}
if (newArmorType != null && e.getRawSlot() == newArmorType.getSlot()) {
EquipMethod method = EquipMethod.PICK_DROP;
if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey) method = EquipMethod.HOTBAR_SWAP;
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType, oldArmorPiece, newArmorPiece);
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
}
}
}
}
@EventHandler
public void playerInteractEvent(PlayerInteractEvent e) {
if (e.getAction() == Action.PHYSICAL) {
return;
}
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
final Player player = e.getPlayer();
if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK) {// Having both of these checks is useless, might as well do it though.
// Some blocks have actions when you right click them which stops the client from equipping the armor in hand.
if (VersionDependentList.getBlackList().stream().anyMatch(type -> e.getClickedBlock().getType().equals(type))) {
return;
}
}
ArmorType newArmorType = ArmorType.matchType(e.getItem());
if (newArmorType != null) {
if (newArmorType.equals(ArmorType.HELMET) && isAirOrNull(e.getPlayer().getInventory().getHelmet()) || newArmorType.equals(ArmorType.CHESTPLATE) && isAirOrNull(e.getPlayer().getInventory().getChestplate()) || newArmorType.equals(ArmorType.LEGGINGS) && isAirOrNull(e.getPlayer().getInventory().getLeggings()) || newArmorType.equals(ArmorType.BOOTS) && isAirOrNull(e.getPlayer().getInventory().getBoots())) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), EquipMethod.HOTBAR, ArmorType.matchType(e.getItem()), null, e.getItem());
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
player.updateInventory();
}
}
}
}
}
@EventHandler
public void inventoryDrag(InventoryDragEvent event) {
// getType() seems to always be even.
// Old Cursor gives the item you are equipping
// Raw slot is the ArmorType slot
// Can't replace armor using this method making getCursor() useless.
ArmorType type = ArmorType.matchType(event.getOldCursor());
if (event.getRawSlots().isEmpty()) return;// Idk if this will ever happen
if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), EquipMethod.DRAG, type, null, event.getOldCursor());
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
event.setResult(Result.DENY);
event.setCancelled(true);
}
}
}
@EventHandler
public void itemBreakEvent(PlayerItemBreakEvent e) {
ArmorType type = ArmorType.matchType(e.getBrokenItem());
if (type != null) {
Player p = e.getPlayer();
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, e.getBrokenItem(), null);
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
ItemStack i = e.getBrokenItem().clone();
i.setAmount(1);
i.setDurability((short) (i.getDurability() - 1));
if (type.equals(ArmorType.HELMET)) {
p.getInventory().setHelmet(i);
} else if (type.equals(ArmorType.CHESTPLATE)) {
p.getInventory().setChestplate(i);
} else if (type.equals(ArmorType.LEGGINGS)) {
p.getInventory().setLeggings(i);
} else if (type.equals(ArmorType.BOOTS)) {
p.getInventory().setBoots(i);
}
}
}
}
@EventHandler
public void playerDeathEvent(PlayerDeathEvent e) {
Player p = e.getEntity();
for (ItemStack i : p.getInventory().getArmorContents()) {
if (!isAirOrNull(i)) {
Bukkit.getServer().getPluginManager().callEvent(new ArmorEquipEvent(p, EquipMethod.DEATH, ArmorType.matchType(i), i, null));
// No way to cancel a death event.
}
}
}
private Location shift(Location start, BlockFace direction, int multiplier) {
if (multiplier == 0) return start;
return new Location(start.getWorld(), start.getX() + direction.getModX() * multiplier, start.getY() + direction.getModY() * multiplier, start.getZ() + direction.getModZ() * multiplier);
}
/**
* A utility method to support versions that use null or air ItemStacks.
*/
private boolean isAirOrNull(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
}

View File

@ -0,0 +1,85 @@
package com.songoda.epicenchants.listeners;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.enums.EnchantResult;
import com.songoda.epicenchants.events.EnchantApplyEvent;
import com.songoda.epicenchants.objects.Enchant;
import de.tr7zw.itemnbtapi.NBTItem;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
public class BookListener implements Listener {
private final EpicEnchants instance;
public BookListener(EpicEnchants instance) {
this.instance = instance;
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onInventoryClick(InventoryClickEvent event) {
if (event.getCursor() == null || event.getCurrentItem() == null || (event.getWhoClicked().getGameMode() != GameMode.CREATIVE && event.getAction() != InventoryAction.SWAP_WITH_CURSOR)) {
return;
}
NBTItem nbtItem = new NBTItem(event.getCursor());
ItemStack toApplyTo = event.getCurrentItem();
boolean incorrectItem = false;
try {
if (!nbtItem.getBoolean("book-item")) {
incorrectItem = true;
return;
}
} catch (NullPointerException ignore) {
incorrectItem = true;
}
if(incorrectItem) return;
Enchant enchant = instance.getEnchantManager().getEnchant(nbtItem.getString("enchant")).orElseThrow(() -> new IllegalStateException("Book without enchant!"));
if (!enchant.getItemWhitelist().contains(toApplyTo.getType())) {
event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("enchant.invalidmaterial", enchant.getIdentifier()));
return;
}
int level = nbtItem.getInteger("level");
int successRate = nbtItem.getInteger("success-rate");
int destroyRate = nbtItem.getInteger("destroy-rate");
EnchantApplyEvent enchantEvent = new EnchantApplyEvent(toApplyTo, enchant, level, successRate, destroyRate);
Bukkit.getPluginManager().callEvent(enchantEvent);
if (enchantEvent.isCancelled()) {
return;
}
Pair<ItemStack, EnchantResult> result = instance.getEnchantUtils().apply(toApplyTo, enchant, enchantEvent.getLevel(), enchantEvent.getSuccessRate(), enchantEvent.getDestroyRate());
switch (result.getRight()) {
case FAILURE:
event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("enchant.failure", enchant.getIdentifier()));
break;
case BROKEN_FAILURE:
event.getCurrentItem().setType(Material.AIR);
event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("enchant.brokenfailure", enchant.getIdentifier()));
break;
case SUCCESS:
event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("enchant.success", enchant.getIdentifier()));
}
event.getWhoClicked().setItemOnCursor(null);
event.getClickedInventory().setItem(event.getSlot(), result.getLeft());
event.setCancelled(true);
}
}

View File

@ -0,0 +1,44 @@
package com.songoda.epicenchants.listeners;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.events.ArmorEquipEvent;
import com.songoda.epicenchants.objects.Enchant;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import java.util.Map;
import static com.songoda.epicenchants.enums.EnchantProcType.*;
public class PlayerListener implements Listener {
private final EpicEnchants instance;
public PlayerListener(EpicEnchants instance) {
this.instance = instance;
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onArmorEquip(ArmorEquipEvent event) {
Map<Enchant, Integer> oldArmorMap = instance.getEnchantUtils().getEnchants(event.getOldArmorPiece());
Map<Enchant, Integer> newArmorMap = instance.getEnchantUtils().getEnchants(event.getNewArmorPiece());
oldArmorMap.forEach((enchant, level) -> enchant.onUnEquip(event.getPlayer(), level));
newArmorMap.forEach((enchant, level) -> enchant.onEquip(event.getPlayer(), level));
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
if (event.getEntityType() != EntityType.PLAYER || (event.getDamager() instanceof Player)) {
return;
}
Player player = (Player) event.getEntity();
Player damager = (Player) event.getDamager();
instance.getEnchantUtils().handlePlayer(player, event, DAMAGED);
instance.getEnchantUtils().handlePlayer(damager, event, DEALT_DAMAGE);
}
}

View File

@ -32,4 +32,9 @@ public class EnchantManager {
public Collection<Enchant> getEnchants() {
return Collections.unmodifiableCollection(enchantMap.values());
}
public Enchant getEnchantUnsafe(String identifier) {
return getEnchant(identifier).orElse(null);
}
}

View File

@ -2,7 +2,8 @@ package com.songoda.epicenchants.managers;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.objects.Enchant;
import com.songoda.epicenchants.utils.ConfigParser;
import com.songoda.epicenchants.utils.Chat;
import com.songoda.epicenchants.utils.parser.ConfigParser;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -17,6 +18,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import static com.songoda.epicenchants.utils.Chat.color;
import static com.songoda.epicenchants.utils.parser.ConfigParser.parseEnchant;
import static java.io.File.separator;
import static java.util.Arrays.asList;
@ -61,7 +64,7 @@ public class FileManager {
File dir = new File(instance.getDataFolder() + separator + "enchants" + separator);
Arrays.stream(dir.listFiles((dir1, filename) -> filename.endsWith(".yml"))).forEach(file -> {
try {
instance.getEnchantManager().addEnchant(loadEnchant(YamlConfiguration.loadConfiguration(file)));
instance.getEnchantManager().addEnchant(parseEnchant(YamlConfiguration.loadConfiguration(file)));
} catch (Exception e) {
Bukkit.getConsoleSender().sendMessage("Something went wrong loading the enchant from file " + file.getName());
Bukkit.getConsoleSender().sendMessage("Please check to make sure there are no errors in the file.");
@ -70,27 +73,6 @@ public class FileManager {
});
}
private Enchant loadEnchant(FileConfiguration config) {
return Enchant.builder()
.identifier(config.getString("identifier"))
.tier(config.getInt("tier"))
.maxLevel(config.getInt("max-tier"))
.format(config.getString("applied-format"))
.action(ConfigParser.parseActionClass(config.getConfigurationSection("action")))
.bookItem(ConfigParser.parseBookItem(config.getConfigurationSection("book-item")))
.itemWhitelist(config.getStringList("item-whitelist").stream().map(Material::valueOf).collect(Collectors.toSet()))
.potionEffects(config.getConfigurationSection("potion-effects").getKeys(false).stream()
.map(s -> "potion-effects." + s)
.map(config::getConfigurationSection)
.map(ConfigParser::parsePotionEffect)
.collect(Collectors.toSet()))
.mobs(config.getConfigurationSection("mobs").getKeys(false).stream()
.map(s -> "mobs." + s)
.map(config::getConfigurationSection)
.map(ConfigParser::parseMobWrapper).collect(Collectors.toSet()))
.build();
}
public FileConfiguration getConfiguration(String key) {
return configurationMap.get(key);
}

View File

@ -1,34 +1,39 @@
package com.songoda.epicenchants.objects;
import com.songoda.epicenchants.enums.EnchantProcType;
import com.songoda.epicenchants.enums.MaterialType;
import com.songoda.epicenchants.wrappers.MobWrapper;
import com.songoda.epicenchants.wrappers.PotionChanceWrapper;
import lombok.Builder;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.Set;
import static com.songoda.epicenchants.objects.ActionClass.DamageType.TAKEN;
import static com.songoda.epicenchants.enums.EnchantProcType.*;
import static com.songoda.epicenchants.enums.MaterialType.*;
@Builder
public class ActionClass {
private Set<PotionChanceWrapper> potionEffectsWearer;
private Set<PotionChanceWrapper> potionEffectOpponent;
private LeveledModifier modifyDamageTaken;
private LeveledModifier modifyDamageGiven;
private LeveledModifier modifyDamage;
private Set<MobWrapper> mobs;
public double run(@NotNull Player wearer, @Nullable Player opponent, int level, double damage, DamageType damageType) {
public double run(@NotNull Player wearer, @Nullable Player opponent, int level, double damage, EnchantProcType procType, MaterialType type) {
potionEffectsWearer.stream().filter(p -> p.test(level)).forEach(p -> p.perform(wearer, level));
Optional.ofNullable(opponent).ifPresent(a -> potionEffectOpponent.stream().filter(p -> p.test(level)).forEach(p -> p.perform(opponent, level)));
if (opponent != null) {
potionEffectOpponent.stream().filter(p -> p.test(level)).forEach(p -> p.perform(opponent, level));
mobs.forEach(mob -> mob.trySpawn(wearer.getLocation(), level));
double percentage = 0;
if((procType == DAMAGED && type == ARMOR) || (procType == DEALT_DAMAGE && type == WEAPON)) {
percentage = modifyDamage.get(level);
}
return damageType == TAKEN ? modifyDamageTaken.get(level) : modifyDamageGiven.get(level);
}
public enum DamageType {
TAKEN, GIVEN
return damage + damage * percentage;
}
}

View File

@ -18,27 +18,35 @@ public class BookItem {
private String displayName;
private List<String> lore;
public ItemStack get(Enchant enchant, int level) {
return get(enchant, level, current().nextDouble(101), current().nextDouble(101));
public ItemStack get(Enchant enchant) {
return get(enchant, current().nextInt(enchant.getMaxLevel()) + 1);
}
public ItemStack get(Enchant enchant, int level, @Optional Double successRate, @Optional Double destroyRate) {
public ItemStack get(Enchant enchant, int level) {
return get(enchant, level, current().nextInt(101), current().nextInt(101));
}
public ItemStack get(Enchant enchant, @Optional Integer level, @Optional Integer successRate, @Optional Integer destroyRate) {
successRate = successRate == null ? current().nextInt(101) : successRate;
destroyRate = destroyRate == null ? current().nextInt(101) : destroyRate;
level = level == null ? current().nextInt(0, enchant.getMaxLevel() + 1) : level;
double finalSuccessRate = successRate;
double finalDestroyRate = destroyRate;
int finalSuccessRate = successRate;
int finalDestroyRate = destroyRate;
int finalLevel = level;
ItemBuilder itemBuilder = new ItemBuilder(material)
.name(displayName.replace("{level}", "" + level))
.lore(lore.stream()
.map(s -> s.replace("{level}", "" + level)
.map(s -> s.replace("{level}", "" + finalLevel)
.replace("{success_rate}", "" + finalSuccessRate)
.replace("{destroy_rate}", "" + finalDestroyRate))
.collect(Collectors.toList()));
NBTItem nbtItem = itemBuilder.nbt();
nbtItem.setDouble("success-rate", successRate);
nbtItem.setDouble("destroy-rate", destroyRate);
nbtItem.setBoolean("book-item", true);
nbtItem.setInteger("success-rate", successRate);
nbtItem.setInteger("destroy-rate", destroyRate);
nbtItem.setInteger("level", level);
nbtItem.setString("enchant", enchant.getIdentifier());
return nbtItem.getItem();

View File

@ -1,22 +1,51 @@
package com.songoda.epicenchants.objects;
import com.songoda.epicenchants.wrappers.MobWrapper;
import com.songoda.epicenchants.enums.MaterialType;
import com.songoda.epicenchants.wrappers.PotionEffectWrapper;
import lombok.Builder;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.Set;
import java.util.stream.Collectors;
import static com.songoda.epicenchants.enums.EnchantProcType.*;
@Builder
@Getter
public class Enchant {
@Getter private String identifier;
@Getter private int tier;
private Set<MobWrapper> mobs;
private String identifier;
private int tier;
private int maxLevel;
private MaterialType materialType;
private Set<PotionEffectWrapper> potionEffects;
private Set<Material> itemWhitelist;
@Getter private int maxLevel;
private String format;
private ActionClass action;
@Getter private BookItem bookItem;
private BookItem bookItem;
public void onEquip(Player player, int level) {
potionEffects.stream().map(p -> p.get(level)).forEach(player::addPotionEffect);
}
public void onUnEquip(Player player, int level) {
Set<PotionEffectType> effects = potionEffects.stream().map(p -> p.get(level)).map(PotionEffect::getType).collect(Collectors.toSet());
player.getActivePotionEffects().stream().map(PotionEffect::getType).filter(effects::contains).forEach(player::removePotionEffect);
}
public void onReceiveDamage(EntityDamageByEntityEvent event, int level) {
event.setDamage(action.run(((Player) event.getEntity()), ((Player) event.getDamager()), level, event.getDamage(), DAMAGED, materialType));
}
public void onDealDamage(EntityDamageByEntityEvent event, int level) {
event.setDamage(action.run(((Player) event.getEntity()), ((Player) event.getDamager()), level, event.getDamage(), DEALT_DAMAGE, materialType));
}
public void onMine(BlockBreakEvent event, int level) {
}
}

View File

@ -1,12 +1,13 @@
package com.songoda.epicenchants.objects;
import org.bukkit.Bukkit;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class LeveledModifier {
private String string;
private static ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
private LeveledModifier(String string) {
this.string = string;
@ -17,9 +18,16 @@ public class LeveledModifier {
}
public double get(int level) {
if (string.isEmpty() || string.equalsIgnoreCase("MAX")) {
return Integer.MAX_VALUE;
}
ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
try {
return Double.parseDouble(scriptEngine.eval(string.replaceAll("\\{level}", "" + level)).toString());
return Double.parseDouble(scriptEngine.eval(string.replace("{level}", "" + level)).toString());
} catch (ScriptException | NumberFormatException e) {
Bukkit.getLogger().warning("[EpicEnchants] One of your math expressions is not properly formatted.");
return 0;
}
}

View File

@ -0,0 +1,79 @@
package com.songoda.epicenchants.utils;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.enums.EnchantProcType;
import com.songoda.epicenchants.enums.EnchantResult;
import com.songoda.epicenchants.objects.Enchant;
import de.tr7zw.itemnbtapi.NBTCompound;
import de.tr7zw.itemnbtapi.NBTItem;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.stream.Collectors;
import static com.songoda.epicenchants.enums.EnchantResult.*;
public class EnchantUtils {
private final EpicEnchants instance;
public EnchantUtils(EpicEnchants instance) {
this.instance = instance;
}
public Pair<ItemStack, EnchantResult> apply(ItemStack itemStack, Enchant enchant, int level, int successRate, int destroyRate) {
if (!GeneralUtils.chance(successRate)) {
return GeneralUtils.chance(destroyRate) ? Pair.of(new ItemStack(Material.AIR), BROKEN_FAILURE) : Pair.of(itemStack, FAILURE);
}
ItemBuilder itemBuilder = new ItemBuilder(itemStack);
itemBuilder.removeLore(enchant.getFormat().replace("{level}", "").trim());
itemBuilder.addLore(enchant.getFormat().replace("{level}", "" + level));
NBTItem nbtItem = itemBuilder.nbt();
nbtItem.addCompound("enchants");
NBTCompound compound = nbtItem.getCompound("enchants");
compound.setInteger(enchant.getIdentifier(), level);
return Pair.of(nbtItem.getItem(), SUCCESS);
}
public Map<Enchant, Integer> getEnchants(ItemStack itemStack) {
if (itemStack == null) {
return Collections.emptyMap();
}
NBTCompound compound = new NBTItem(itemStack).getCompound("enchants");
if (compound == null) {
return Collections.emptyMap();
}
return compound.getKeys().stream().collect(Collectors.toMap(key -> instance.getEnchantManager().getEnchantUnsafe(key), compound::getInteger));
}
public void handlePlayer(Player player, Event event, EnchantProcType damageType) {
List<ItemStack> stacks = Arrays.asList(player.getInventory().getArmorContents());
stacks.add(player.getItemInHand());
stacks.removeIf(Objects::isNull);
stacks.stream().map(this::getEnchants).forEach(list -> list.forEach((enchant, level) -> {
switch (damageType) {
case DAMAGED:
enchant.onReceiveDamage((EntityDamageByEntityEvent) event, level);
case DEALT_DAMAGE:
enchant.onDealDamage((EntityDamageByEntityEvent) event, level);
case MINED:
enchant.onMine((BlockBreakEvent) event, level);
}
}));
}
}

View File

@ -3,7 +3,11 @@ package com.songoda.epicenchants.utils;
import java.util.concurrent.ThreadLocalRandom;
public class GeneralUtils {
public static boolean chance(Double chance) {
public static boolean chance(int chance) {
return chance((double) chance);
}
public static boolean chance(double chance) {
return ThreadLocalRandom.current().nextDouble(101) < chance;
}
}

View File

@ -1,5 +1,6 @@
package com.songoda.epicenchants.utils;
import com.songoda.epicenchants.utils.parser.ConfigParser;
import com.songoda.epicenchants.wrappers.EnchantmentWrapper;
import de.tr7zw.itemnbtapi.NBTItem;
import org.bukkit.Material;
@ -113,6 +114,15 @@ public class ItemBuilder {
return this;
}
public ItemBuilder removeLore(String string) {
if(!meta.hasLore()) {
return this;
}
meta.setLore(meta.getLore().stream().filter(s -> !s.startsWith(string)).collect(Collectors.toList()));
return this;
}
public ItemBuilder addLore(String... lore) {
return addLore(Arrays.asList(lore));
}

View File

@ -0,0 +1,172 @@
package com.songoda.epicenchants.utils;
import org.bukkit.Material;
import java.util.HashSet;
import java.util.Set;
public class VersionDependentList {
private static Set<Material> blacklistLegacy;
private static Set<Material> blacklist;
public static void initLegacy() {
blacklistLegacy = new HashSet<Material>() {
{
add(Material.valueOf("FURNACE"));
add(Material.valueOf("CHEST"));
add(Material.valueOf("TRAPPED_CHEST"));
add(Material.valueOf("BEACON"));
add(Material.valueOf("DISPENSER"));
add(Material.valueOf("DROPPER"));
add(Material.valueOf("HOPPER"));
add(Material.valueOf("WORKBENCH"));
add(Material.valueOf("ENCHANTMENT_TABLE"));
add(Material.valueOf("ENDER_CHEST"));
add(Material.valueOf("ANVIL"));
add(Material.valueOf("BED_BLOCK"));
add(Material.valueOf("FENCE_GATE"));
add(Material.valueOf("SPRUCE_FENCE_GATE"));
add(Material.valueOf("BIRCH_FENCE_GATE"));
add(Material.valueOf("ACACIA_FENCE_GATE"));
add(Material.valueOf("JUNGLE_FENCE_GATE"));
add(Material.valueOf("DARK_OAK_FENCE_GATE"));
add(Material.valueOf("IRON_DOOR_BLOCK"));
add(Material.valueOf("WOODEN_DOOR"));
add(Material.valueOf("SPRUCE_DOOR"));
add(Material.valueOf("BIRCH_DOOR"));
add(Material.valueOf("JUNGLE_DOOR"));
add(Material.valueOf("ACACIA_DOOR"));
add(Material.valueOf("DARK_OAK_DOOR"));
add(Material.valueOf("WOOD_BUTTON"));
add(Material.valueOf("STONE_BUTTON"));
add(Material.valueOf("TRAP_DOOR"));
add(Material.valueOf("IRON_TRAPDOOR"));
add(Material.valueOf("DIODE_BLOCK_OFF"));
add(Material.valueOf("DIODE_BLOCK_ON"));
add(Material.valueOf("REDSTONE_COMPARATOR_OFF"));
add(Material.valueOf("REDSTONE_COMPARATOR_ON"));
add(Material.valueOf("FENCE"));
add(Material.valueOf("SPRUCE_FENCE"));
add(Material.valueOf("BIRCH_FENCE"));
add(Material.valueOf("JUNGLE_FENCE"));
add(Material.valueOf("DARK_OAK_FENCE"));
add(Material.valueOf("ACACIA_FENCE"));
add(Material.valueOf("NETHER_FENCE"));
add(Material.valueOf("BREWING_STAND"));
add(Material.valueOf("CAULDRON"));
add(Material.valueOf("SIGN_POST"));
add(Material.valueOf("WALL_SIGN"));
add(Material.valueOf("SIGN"));
add(Material.valueOf("LEVER"));
add(Material.valueOf("DAYLIGHT_DETECTOR_INVERTED"));
add(Material.valueOf("DAYLIGHT_DETECTOR"));
}
};
}
public static void initDefault() {
blacklist = new HashSet<Material>() {
{
add(Material.valueOf("FURNACE"));
add(Material.valueOf("CHEST"));
add(Material.valueOf("TRAPPED_CHEST"));
add(Material.valueOf("BEACON"));
add(Material.valueOf("DISPENSER"));
add(Material.valueOf("DROPPER"));
add(Material.valueOf("HOPPER"));
add(Material.valueOf("CRAFTING_TABLE"));
add(Material.valueOf("ENCHANTING_TABLE"));
add(Material.valueOf("BLACK_BED"));
add(Material.valueOf("BLUE_BED"));
add(Material.valueOf("BROWN_BED"));
add(Material.valueOf("CYAN_BED"));
add(Material.valueOf("GRAY_BED"));
add(Material.valueOf("GREEN_BED"));
add(Material.valueOf("LIGHT_BLUE_BED"));
add(Material.valueOf("LIGHT_GRAY_BED"));
add(Material.valueOf("LIME_BED"));
add(Material.valueOf("MAGENTA_BED"));
add(Material.valueOf("ORANGE_BED"));
add(Material.valueOf("PINK_BED"));
add(Material.valueOf("PURPLE_BED"));
add(Material.valueOf("RED_BED"));
add(Material.valueOf("WHITE_BED"));
add(Material.valueOf("YELLOW_BED"));
add(Material.valueOf("ENDER_CHEST"));
add(Material.valueOf("ANVIL"));
add(Material.valueOf("ACACIA_FENCE_GATE"));
add(Material.valueOf("BIRCH_FENCE_GATE"));
add(Material.valueOf("DARK_OAK_FENCE_GATE"));
add(Material.valueOf("JUNGLE_FENCE_GATE"));
add(Material.valueOf("OAK_FENCE_GATE"));
add(Material.valueOf("SPRUCE_FENCE_GATE"));
add(Material.valueOf("IRON_DOOR"));
add(Material.valueOf("ACACIA_DOOR"));
add(Material.valueOf("BIRCH_DOOR"));
add(Material.valueOf("DARK_OAK_DOOR"));
add(Material.valueOf("JUNGLE_DOOR"));
add(Material.valueOf("OAK_DOOR"));
add(Material.valueOf("SPRUCE_DOOR"));
add(Material.valueOf("ACACIA_TRAPDOOR"));
add(Material.valueOf("BIRCH_TRAPDOOR"));
add(Material.valueOf("DARK_OAK_TRAPDOOR"));
add(Material.valueOf("JUNGLE_TRAPDOOR"));
add(Material.valueOf("OAK_TRAPDOOR"));
add(Material.valueOf("SPRUCE_TRAPDOOR"));
add(Material.valueOf("ACACIA_BUTTON"));
add(Material.valueOf("BIRCH_BUTTON"));
add(Material.valueOf("DARK_OAK_BUTTON"));
add(Material.valueOf("JUNGLE_BUTTON"));
add(Material.valueOf("OAK_BUTTON"));
add(Material.valueOf("SPRUCE_BUTTON"));
add(Material.valueOf("ACACIA_FENCE"));
add(Material.valueOf("BIRCH_FENCE"));
add(Material.valueOf("DARK_OAK_FENCE"));
add(Material.valueOf("JUNGLE_FENCE"));
add(Material.valueOf("OAK_FENCE"));
add(Material.valueOf("SPRUCE_FENCE"));
add(Material.valueOf("REPEATER"));
add(Material.valueOf("COMPARATOR"));
add(Material.valueOf("BREWING_STAND"));
add(Material.valueOf("CAULDRON"));
add(Material.valueOf("WALL_SIGN"));
add(Material.valueOf("SIGN"));
add(Material.valueOf("LEVER"));
add(Material.valueOf("DAYLIGHT_DETECTOR"));
add(Material.valueOf("SHULKER_BOX"));
add(Material.valueOf("BLACK_SHULKER_BOX"));
add(Material.valueOf("BLUE_SHULKER_BOX"));
add(Material.valueOf("BROWN_SHULKER_BOX"));
add(Material.valueOf("CYAN_SHULKER_BOX"));
add(Material.valueOf("GRAY_SHULKER_BOX"));
add(Material.valueOf("GREEN_SHULKER_BOX"));
add(Material.valueOf("LIGHT_BLUE_SHULKER_BOX"));
add(Material.valueOf("LIGHT_GRAY_SHULKER_BOX"));
add(Material.valueOf("LIME_SHULKER_BOX"));
add(Material.valueOf("MAGENTA_SHULKER_BOX"));
add(Material.valueOf("ORANGE_SHULKER_BOX"));
add(Material.valueOf("PINK_SHULKER_BOX"));
add(Material.valueOf("PURPLE_SHULKER_BOX"));
add(Material.valueOf("RED_SHULKER_BOX"));
add(Material.valueOf("WHITE_SHULKER_BOX"));
add(Material.valueOf("YELLOW_SHULKER_BOX"));
}
};
}
public static Set<Material> getBlackList() {
return !blacklist.isEmpty() ? blacklist : !blacklistLegacy.isEmpty() ? blacklistLegacy : null;
}
}

View File

@ -1,11 +1,13 @@
package com.songoda.epicenchants.utils;
package com.songoda.epicenchants.utils.parser;
import com.songoda.epicenchants.objects.ActionClass;
import com.songoda.epicenchants.objects.BookItem;
import com.songoda.epicenchants.objects.LeveledModifier;
import com.songoda.epicenchants.enums.MaterialType;
import com.songoda.epicenchants.objects.*;
import com.songoda.epicenchants.utils.Chat;
import com.songoda.epicenchants.utils.ItemBuilder;
import com.songoda.epicenchants.wrappers.*;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.potion.PotionEffectType;
@ -15,12 +17,33 @@ import java.util.stream.Collectors;
import static com.songoda.epicenchants.utils.Chat.color;
public class ConfigParser {
public static Enchant parseEnchant(FileConfiguration config) {
return Enchant.builder()
.identifier(config.getString("identifier"))
.tier(config.getInt("tier"))
.materialType(MaterialType.of(config.getString("type")))
.maxLevel(config.getInt("max-level"))
.format(color(config.getString("applied-format")))
.action(parseActionClass(config.getConfigurationSection("action")))
.bookItem(parseBookItem(config.getConfigurationSection("book-item")))
.itemWhitelist(config.getStringList("item-whitelist").stream().map(Material::valueOf).collect(Collectors.toSet()))
.potionEffects(config.getConfigurationSection("potion-effects").getKeys(false).stream()
.map(s -> "potion-effects." + s)
.map(config::getConfigurationSection)
.map(ConfigParser::parsePotionEffect)
.collect(Collectors.toSet()))
.build();
}
public static ActionClass parseActionClass(ConfigurationSection section) {
return ActionClass.builder()
.modifyDamageGiven(LeveledModifier.of(section.getString("modify-damage-given")))
.modifyDamageTaken(LeveledModifier.of(section.getString("modify-damage-taken")))
.potionEffectsWearer(ConfigParser.getPotionChanceSet(section.getConfigurationSection("potion-effects-defendant")))
.modifyDamage(LeveledModifier.of(section.getString("modify-damage")))
.potionEffectsWearer(ConfigParser.getPotionChanceSet(section.getConfigurationSection("potion-effects-wearer")))
.potionEffectOpponent(ConfigParser.getPotionChanceSet(section.getConfigurationSection("potion-effects-opponent")))
.mobs(section.getConfigurationSection("mobs").getKeys(false).stream()
.map(s -> "mobs." + s)
.map(section::getConfigurationSection)
.map(ConfigParser::parseMobWrapper).collect(Collectors.toSet()))
.build();
}
@ -59,7 +82,7 @@ public class ConfigParser {
.helmet(new ItemBuilder(section.getConfigurationSection("armor.helmet")))
.leggings(new ItemBuilder(section.getConfigurationSection("armor.chest-plate")))
.chestPlate(new ItemBuilder(section.getConfigurationSection("armor.leggings")))
.boots(new ItemBuilder(section.getConfigurationSection("armor.boots")).build())
.boots(new ItemBuilder(section.getConfigurationSection("armor.boots")))
.build();
}

View File

@ -1,7 +1,8 @@
package com.songoda.epicenchants.utils;
package com.songoda.epicenchants.utils.parser;
import com.songoda.epicenchants.EpicEnchants;
import com.songoda.epicenchants.objects.Enchant;
import com.songoda.epicenchants.utils.ItemBuilder;
import fr.minuskube.inv.ClickableItem;
import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
@ -32,17 +33,14 @@ public class InventoryParser {
.filter(StringUtils::isNumeric)
.map(s -> "contents." + s)
.map(config::getConfigurationSection)
.forEach(config -> {
double expCost = config.getDouble("exp-cost");
double ecoCost = config.getDouble("eco-cost");
int tier = config.getInt("tier");
inventoryContents.set(config.getInt("row"), config.getInt("column"), ClickableItem.of(new ItemBuilder(config).build(), event -> {
.forEach(section -> {
double expCost = section.getDouble("exp-cost");
double ecoCost = section.getDouble("eco-cost");
int tier = section.getInt("tier");
inventoryContents.set(section.getInt("row"), section.getInt("column"), ClickableItem.of(new ItemBuilder(section).build(), event -> {
Player player = ((Player) event.getWhoClicked());
if (!instance.getEconomy().has((player), ecoCost) || (player).getLevel() < expCost) {
player
.sendMessage(instance
.getLocale().getPrefix() + instance.getLocale()
.getMessage("event.purchase.cannotafford"));
player.sendMessage(instance.getLocale().getPrefix() + instance.getLocale().getMessage("event.purchase.cannotafford"));
return;
}
@ -55,8 +53,8 @@ public class InventoryParser {
instance.getEconomy().withdrawPlayer(player, ecoCost);
player.setLevel((int) (player.getLevel() - expCost));
player.getInventory().addItem(enchant.get().getBookItem().get(enchant.get(), current().nextInt(enchant.get().getMaxLevel() + 1)));
player.sendMessage(instance.getLocale().getPrefix() + instance.getLocale().getMessage("event.purchase.successful"));
player.getInventory().addItem(enchant.get().getBookItem().get(enchant.get()));
player.sendMessage(instance.getLocale().getPrefix() + instance.getLocale().getMessage("event.purchase.success", "" + tier));
}));
});
}

View File

@ -14,6 +14,6 @@ public class PotionEffectWrapper {
private LeveledModifier duration;
public PotionEffect get(int level) {
return new PotionEffect(type, (int) amplifier.get(level), (int) duration.get(level));
return new PotionEffect(type, (int) duration.get(level), (int) amplifier.get(level) - 1);
}
}

View File

@ -1,7 +1,7 @@
#The enchant identifier must be unique
identifier: Strength
#The max level for this enchant
#The max tier for this enchant
max-level: 3
#The tier of this enchant
@ -28,50 +28,53 @@ item-whitelist:
#Potion effects applied on equip
potion-effects:
INCREASE_DAMAGE:
amplifier: {level}
amplifier: "{level}"
duration: MAX
#Spawned when hit or when you strike an enemy in case of tools
mobs:
IRON_GOLEM:
amount: 3
spawn-percentage: 20
health: 80
attack-damage: 2
hostile: true
display-name: "&cAngry guy"
armor:
helmet:
material: DIAMOND_HELMET
enchants:
- "DURABILITY:3"
- "THORNS:2"
chest-plate:
material: DIAMOND_CHESTPLATE
enchants:
- "DURABILITY:3"
- "THORNS:2"
leggings:
material: DIAMOND_LEGGINGS
enchants:
- "DURABILITY:3"
- "THORNS:2"
boots:
material: DIAMOND_BOOTS
enchants:
- "DURABILITY:3"
- "THORNS:2"
#Type of material this enchant will be applied to (WEAPON/ARMOR/TOOL)
type: ARMOR
#On hit or deal damage
action:
modify-damage-taken: 40
modify-damage-given: -10
#Percentage that will be added or subtracted from the total damage.
modify-damage: 40
potion-effects-wearer:
STRENGTH:
duration: 3
chance: 20 * {level}
chance: "20 * {level}"
amplifier: 2
potion-effects-opponent:
STRENGTH:
duration: 3
chance: 20 * {level}
amplifier: 2
chance: "20 * {level}"
amplifier: 2
#Spawned when hit or when you strike an enemy in case of tools
mobs:
IRON_GOLEM:
amount: 3
spawn-percentage: 20
health: 80
attack-damage: 2
hostile: true
display-name: "&cAngry guy"
armor:
helmet:
material: DIAMOND_HELMET
enchants:
- "DURABILITY:3"
- "THORNS:2"
chest-plate:
material: DIAMOND_CHESTPLATE
enchants:
- "DURABILITY:3"
- "THORNS:2"
leggings:
material: DIAMOND_LEGGINGS
enchants:
- "DURABILITY:3"
- "THORNS:2"
boots:
material: DIAMOND_BOOTS
enchants:
- "DURABILITY:3"
- "THORNS:2"

View File

@ -12,7 +12,7 @@ contents:
display-name: "&cClick to purchase random book"
data: 7
tier: 1
exp-cost: 2000
exp-cost: 20
eco-cost: 2000
row: 3
column: 5
row: 1
column: 4

View File

@ -1 +1 @@
language: en_US
language: "en_US"

View File

@ -12,3 +12,9 @@ event.general.nopermission= "&cYou do not have permission to do that."
event.purchase.noenchant= "&cThere is no enchant available for &6tier {tier}&7."
event.purchase.cannotafford= "&cYou cannot afford this purchase."
event.purchase.success= "&7You successfully purchased a &6tier {tier} &7Book."
#Enchant Messages
enchant.invalidmaterial= "&cYou can not apply &6{enchant} to that item."
enchant.failure= "&cYou failed to apply &6{enchant}."
enchant.brokenfailure= "&6{enchant} failed to apply and broke your item..."
enchant.success= "&aYou have success fully applied &6{enchant}."

View File

@ -3,4 +3,5 @@ version: ${project.version}
main: com.songoda.epicenchants.EpicEnchants
authors: [GB6]
website: https://songoda.com/
depend: [Vault]
depend: [Vault]
api-version: 1.13