mirror of
https://github.com/songoda/EpicEnchants.git
synced 2024-11-14 22:56:20 +01:00
- Added the alchemist
- Moved the ee enchanter ee tinkerer ee alchemist into separate commands. (/enchanter /tinkerer /alchemist) - Added {user_holding} {opponent_holding} variables. - Added {user_is_swimming} {opponent_is_swimming} variables. - CONSOLE_COMMAND, MESSAGE and PLAYER_COMMAND now support multiples lines of string to handle
This commit is contained in:
parent
f8bd9e31eb
commit
817aa2cb8d
@ -8,15 +8,18 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.songoda.epicenchants.utils.single.GeneralUtils.color;
|
||||
|
||||
public class Action {
|
||||
private FileConfiguration config;
|
||||
private String prefix;
|
||||
|
||||
public void perform(CommandSender sender, String node, Placeholder... placeholders) {
|
||||
if (config.isString(node)) {
|
||||
sender.sendMessage(getMessage(node, placeholders));
|
||||
getMessage(node, placeholders).forEach(sender::sendMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -26,8 +29,8 @@ public class Action {
|
||||
|
||||
ConfigurationSection section = config.getConfigurationSection(node);
|
||||
|
||||
if (section.isString("message")) {
|
||||
sender.sendMessage(getMessage(node + ".message", placeholders));
|
||||
if (section.isString("message") || section.isList("message")) {
|
||||
getMessage(node + ".message", placeholders).forEach(sender::sendMessage);
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
@ -46,18 +49,19 @@ public class Action {
|
||||
|
||||
}
|
||||
|
||||
public String getMessage(String node, Placeholder... placeholders) {
|
||||
String string = config.getString(node);
|
||||
public List<String> getMessage(String node, Placeholder... placeholders) {
|
||||
List<String> output = config.isList(node) ? config.getStringList(node) : Collections.singletonList(config.getString(node));
|
||||
|
||||
for (Placeholder placeholder : placeholders) {
|
||||
string = string.replace(placeholder.getPlaceholder(), placeholder.getToReplace().toString());
|
||||
}
|
||||
return output.stream().map(s -> {
|
||||
for (Placeholder placeholder : placeholders) {
|
||||
s = s.replace(placeholder.getPlaceholder(), placeholder.getToReplace().toString());
|
||||
}
|
||||
|
||||
return color(string);
|
||||
return color(s);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void load(FileConfiguration config) {
|
||||
this.config = config;
|
||||
this.prefix = config.getString("general.prefix");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.songoda.epicenchants.commands;
|
||||
|
||||
import co.aikar.commands.BaseCommand;
|
||||
import co.aikar.commands.annotation.*;
|
||||
import com.songoda.epicenchants.EpicEnchants;
|
||||
import com.songoda.epicenchants.menus.AlchemistMenu;
|
||||
import com.songoda.epicenchants.menus.EnchanterMenu;
|
||||
import com.songoda.epicenchants.menus.TinkererMenu;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class CustomCommand extends BaseCommand {
|
||||
|
||||
@Dependency("instance")
|
||||
private EpicEnchants instance;
|
||||
|
||||
@CommandAlias("%enchanter")
|
||||
@Description("Opens the Enchanter")
|
||||
@CommandPermission("epicenchants.enchanter")
|
||||
public void onEnchanter(Player player) {
|
||||
new EnchanterMenu(instance, instance.getFileManager().getConfiguration("menus/enchanter-menu"), player).open(player);
|
||||
}
|
||||
|
||||
@CommandAlias("%tinkerer")
|
||||
@Description("Opens the Tinkerer")
|
||||
@CommandPermission("epicenchants.tinkerer")
|
||||
public void onTinkerer(Player player) {
|
||||
new TinkererMenu(instance, instance.getFileManager().getConfiguration("menus/tinkerer-menu")).open(player);
|
||||
}
|
||||
|
||||
@CommandAlias("%alchemist")
|
||||
@Description("Opens the Alchemist")
|
||||
@CommandPermission("epicenchants.alchemist")
|
||||
public void onAlchemist(Player player) {
|
||||
new AlchemistMenu(instance, instance.getFileManager().getConfiguration("menus/alchemist-menu")).open(player);
|
||||
}
|
||||
|
||||
}
|
@ -5,8 +5,6 @@ import co.aikar.commands.CommandHelp;
|
||||
import co.aikar.commands.annotation.*;
|
||||
import com.songoda.epicenchants.EpicEnchants;
|
||||
import com.songoda.epicenchants.enums.EnchantResult;
|
||||
import com.songoda.epicenchants.menus.EnchanterMenu;
|
||||
import com.songoda.epicenchants.menus.TinkererMenu;
|
||||
import com.songoda.epicenchants.objects.Enchant;
|
||||
import com.songoda.epicenchants.objects.Group;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@ -24,20 +22,6 @@ public class EnchantCommand extends BaseCommand {
|
||||
@Dependency("instance")
|
||||
private EpicEnchants instance;
|
||||
|
||||
@Subcommand("%enchanter")
|
||||
@Description("Opens the Enchanter")
|
||||
@CommandPermission("epicenchants.enchanter")
|
||||
public void onEnchanter(Player player) {
|
||||
new EnchanterMenu(instance, instance.getFileManager().getConfiguration("menus/enchanter-menu"), player).open(player);
|
||||
}
|
||||
|
||||
@Subcommand("%tinkerer")
|
||||
@Description("Opens the Tinkerer")
|
||||
@CommandPermission("epicenchants.tinkerer")
|
||||
public void onTinkerer(Player player) {
|
||||
new TinkererMenu(instance, instance.getFileManager().getConfiguration("menus/tinkerer-menu")).open(player);
|
||||
}
|
||||
|
||||
//ee give book [player] [enchant] <level> <success-rate> <destroy-rate>
|
||||
@Subcommand("give book")
|
||||
@CommandCompletion("@players @enchants @levels @increment @increment")
|
||||
@ -68,10 +52,10 @@ public class EnchantCommand extends BaseCommand {
|
||||
|
||||
//ee give item [giveType] [player] <amount> <success-rate>
|
||||
@Subcommand("give item")
|
||||
@CommandCompletion("@players @giveType @nothing @nothing")
|
||||
@CommandCompletion("@giveType @players @nothing @nothing")
|
||||
@Description("Give enchant books to players")
|
||||
@CommandPermission("epicenchants.give.item")
|
||||
public void onGiveItem(CommandSender sender, @Flags("other") Player target, String giveType, @Optional Integer amount, @Optional Integer successRate) {
|
||||
public void onGiveItem(CommandSender sender, String giveType, @Flags("other") Player target, @Optional Integer amount, @Optional Integer successRate) {
|
||||
String messageKey;
|
||||
switch (giveType.toLowerCase()) {
|
||||
case "whitescroll":
|
||||
|
@ -13,21 +13,31 @@ import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.songoda.epicenchants.effect.EffectExecutor.Who.OPPONENT;
|
||||
import static com.songoda.epicenchants.effect.EffectExecutor.Who.USER;
|
||||
import static com.songoda.epicenchants.effect.EffectExecutor.Who.*;
|
||||
|
||||
public abstract class EffectExecutor {
|
||||
@Getter private final ConfigurationSection section;
|
||||
@Getter private final Set<TriggerType> triggerTypes;
|
||||
private final Set<EffectExecutor> simultaneous;
|
||||
private final Condition condition;
|
||||
|
||||
public EffectExecutor(ConfigurationSection section) {
|
||||
this.section = section;
|
||||
this.triggerTypes = GeneralUtils.parseTrigger(section.getString("trigger"));
|
||||
this.condition = Condition.of(section.getString("condition"));
|
||||
this.simultaneous = section.isConfigurationSection("effects") ? section.getConfigurationSection("effects").getKeys(false).stream()
|
||||
.map(s -> "effects." + s)
|
||||
.map(section::getConfigurationSection)
|
||||
.map(EffectManager::getEffect)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.collect(Collectors.toSet()) : Collections.emptySet();
|
||||
}
|
||||
|
||||
public void testAndRun(@NotNull Player user, @Nullable LivingEntity opponent, int level, TriggerType type, Event event, EventType eventType) {
|
||||
@ -45,10 +55,11 @@ public abstract class EffectExecutor {
|
||||
|
||||
if (this instanceof EffectEventExecutor) {
|
||||
((EffectEventExecutor) this).execute(user, opponent, level, event, eventType);
|
||||
return;
|
||||
} else {
|
||||
execute(user, opponent, level, eventType);
|
||||
}
|
||||
|
||||
execute(user, opponent, level, eventType);
|
||||
simultaneous.forEach(e -> e.execute(user, opponent, level, eventType));
|
||||
}
|
||||
|
||||
public abstract void execute(@NotNull Player user, @Nullable LivingEntity opponent, int level, EventType eventType);
|
||||
|
@ -2,6 +2,7 @@ package com.songoda.epicenchants.effect.effects;
|
||||
|
||||
import com.songoda.epicenchants.effect.EffectExecutor;
|
||||
import com.songoda.epicenchants.enums.EventType;
|
||||
import com.songoda.epicenchants.utils.single.GeneralUtils;
|
||||
import com.songoda.epicenchants.utils.single.Placeholders;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@ -16,7 +17,8 @@ public class ConsoleCommand extends EffectExecutor {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player user, LivingEntity opponent, int level, EventType eventType) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
|
||||
Placeholders.setPlaceholders(getSection().getString("command"), user, opponent, level));
|
||||
GeneralUtils.getString(getSection(), "command").stream()
|
||||
.map(s -> Placeholders.setPlaceholders(s, user, opponent, level))
|
||||
.forEach(s -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), s));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.songoda.epicenchants.effect.effects;
|
||||
|
||||
import com.songoda.epicenchants.effect.EffectExecutor;
|
||||
import com.songoda.epicenchants.enums.EventType;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Explode extends EffectExecutor {
|
||||
public Explode(ConfigurationSection section) {
|
||||
super(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player user, @Nullable LivingEntity opponent, int level, EventType eventType) {
|
||||
consume(entity -> entity.getWorld().createExplosion(entity.getLocation(), getSection().getInt("magnitude")), user, opponent);
|
||||
}
|
||||
}
|
@ -2,14 +2,13 @@ package com.songoda.epicenchants.effect.effects;
|
||||
|
||||
import com.songoda.epicenchants.effect.EffectExecutor;
|
||||
import com.songoda.epicenchants.enums.EventType;
|
||||
import com.songoda.epicenchants.utils.single.GeneralUtils;
|
||||
import com.songoda.epicenchants.utils.single.Placeholders;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.songoda.epicenchants.utils.single.GeneralUtils.color;
|
||||
|
||||
public class Message extends EffectExecutor {
|
||||
public Message(ConfigurationSection section) {
|
||||
super(section);
|
||||
@ -17,7 +16,10 @@ public class Message extends EffectExecutor {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull Player user, LivingEntity opponent, int level, EventType eventType) {
|
||||
if (eventType == EventType.ON || eventType == EventType.NONE)
|
||||
consume(entity -> entity.sendMessage(color(Placeholders.setPlaceholders(getSection().getString("message"), user, opponent, level))), user, opponent);
|
||||
if (eventType == EventType.ON || eventType == EventType.NONE) {
|
||||
consume(entity -> GeneralUtils.getString(getSection(), "message").stream()
|
||||
.map(s -> Placeholders.setPlaceholders(s, user, opponent, level))
|
||||
.forEach(entity::sendMessage), user, opponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,12 @@ public class ModifyBlock extends EffectEventExecutor {
|
||||
}
|
||||
|
||||
Block block = event instanceof BlockEvent ? ((BlockEvent) event).getBlock() : ((PlayerInteractEvent) event).getClickedBlock();
|
||||
|
||||
if (getSection().getBoolean("break-naturally")) {
|
||||
block.breakNaturally();
|
||||
return;
|
||||
}
|
||||
|
||||
block.setType(Material.getMaterial(getSection().getString("material")));
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.songoda.epicenchants.effect.effects;
|
||||
|
||||
import com.songoda.epicenchants.effect.EffectExecutor;
|
||||
import com.songoda.epicenchants.enums.EventType;
|
||||
import com.songoda.epicenchants.utils.single.GeneralUtils;
|
||||
import com.songoda.epicenchants.utils.single.Placeholders;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
@ -9,8 +10,7 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.songoda.epicenchants.effect.EffectExecutor.Who.OPPONENT;
|
||||
import static com.songoda.epicenchants.enums.EventType.NONE;
|
||||
import static com.songoda.epicenchants.enums.EventType.ON;
|
||||
import static com.songoda.epicenchants.enums.EventType.*;
|
||||
|
||||
public class PlayerCommand extends EffectExecutor {
|
||||
public PlayerCommand(ConfigurationSection section) {
|
||||
@ -27,7 +27,8 @@ public class PlayerCommand extends EffectExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
consume(entity -> ((Player) entity).performCommand(Placeholders.setPlaceholders(getSection().getString("command"), user, opponent, level)), user, opponent);
|
||||
|
||||
consume(entity -> GeneralUtils.getString(getSection(), "message").stream()
|
||||
.map(s -> Placeholders.setPlaceholders(s, user, opponent, level))
|
||||
.forEach(((Player) entity)::performCommand), user, opponent);
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.songoda.epicenchants.utils.single.Experience.changeExp;
|
||||
import static com.songoda.epicenchants.utils.single.Experience.getExp;
|
||||
import static com.songoda.epicenchants.utils.single.Experience.*;
|
||||
|
||||
public class StealExp extends EffectExecutor {
|
||||
public StealExp(ConfigurationSection section) {
|
||||
@ -24,13 +23,16 @@ public class StealExp extends EffectExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) opponent;
|
||||
Player opponentPlayer = (Player) opponent;
|
||||
|
||||
if (amount > getExp(opponentPlayer)) {
|
||||
amount = getExp(opponentPlayer);
|
||||
}
|
||||
|
||||
if (getExp(player) - amount <= 0) {
|
||||
changeExp(player, 0);
|
||||
if (getExp(opponentPlayer) - amount <= 0) {
|
||||
changeExp(opponentPlayer, 0);
|
||||
} else {
|
||||
changeExp(player, (int) -amount);
|
||||
changeExp(opponentPlayer, (int) -amount);
|
||||
}
|
||||
|
||||
if (getExp(user) + amount <= 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
package com.songoda.epicenchants.enums;
|
||||
|
||||
public enum GiveType {
|
||||
WHITE_SCROLL, BLACK_SCROLL, DUST
|
||||
WHITE_SCROLL, BLACK_SCROLL
|
||||
}
|
||||
|
@ -27,5 +27,6 @@ public enum TriggerType {
|
||||
|
||||
BLOCK_BREAK,
|
||||
REPEATING,
|
||||
RIGHT_CLICK
|
||||
RIGHT_CLICK,
|
||||
LEFT_CLICK
|
||||
}
|
||||
|
@ -58,6 +58,8 @@ public class PlayerListener implements Listener {
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||
instance.getEnchantUtils().handlePlayer(event.getPlayer(), null, event, RIGHT_CLICK);
|
||||
} else if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) {
|
||||
instance.getEnchantUtils().handlePlayer(event.getPlayer(), null, event, LEFT_CLICK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ public class BookListener extends ItemListener {
|
||||
return;
|
||||
}
|
||||
|
||||
Group group = instance.getGroupManager().getValueUnsafe(clicked.getString("group"));
|
||||
Group group = instance.getGroupManager().getValue(clicked.getString("group")).orElseThrow(() -> new IllegalStateException("Book without group!"));
|
||||
|
||||
Optional<Enchant> enchant = instance.getEnchantManager().getRandomEnchant(group);
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.songoda.epicenchants.managers;
|
||||
import co.aikar.commands.BukkitCommandManager;
|
||||
import co.aikar.commands.InvalidCommandArgument;
|
||||
import com.songoda.epicenchants.EpicEnchants;
|
||||
import com.songoda.epicenchants.commands.CustomCommand;
|
||||
import com.songoda.epicenchants.commands.EnchantCommand;
|
||||
import com.songoda.epicenchants.enums.GiveType;
|
||||
import com.songoda.epicenchants.objects.Enchant;
|
||||
@ -70,5 +71,6 @@ public class CommandManager extends BukkitCommandManager {
|
||||
// COMMANDS
|
||||
|
||||
registerCommand(new EnchantCommand());
|
||||
registerCommand(new CustomCommand());
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ public class FileManager extends Manager<String, FileConfiguration> {
|
||||
of("menus/main-info-menu.yml", true),
|
||||
of("menus/enchanter-menu.yml", true, true),
|
||||
of("menus/tinkerer-menu.yml", true, true),
|
||||
of("menus/alchemist-menu.yml", true, true),
|
||||
of("menus/groups/simple-menu.yml", false),
|
||||
of("menus/groups/unique-menu.yml", false),
|
||||
of("menus/groups/elite-menu.yml", false),
|
||||
@ -38,10 +39,8 @@ public class FileManager extends Manager<String, FileConfiguration> {
|
||||
|
||||
public FileManager(EpicEnchants instance) {
|
||||
super(instance);
|
||||
|
||||
directory = instance.getVersion() > 12 ? "master" : "legacy";
|
||||
|
||||
Bukkit.getConsoleSender().sendMessage("Using the " + directory + " because version is 1." + instance.getVersion());
|
||||
Bukkit.getConsoleSender().sendMessage("Using the " + directory + " configurations because version is 1." + instance.getVersion());
|
||||
}
|
||||
|
||||
public void loadFiles() {
|
||||
|
@ -1,34 +1,288 @@
|
||||
package com.songoda.epicenchants.menus;
|
||||
|
||||
import com.songoda.epicenchants.EpicEnchants;
|
||||
import com.songoda.epicenchants.objects.Enchant;
|
||||
import com.songoda.epicenchants.objects.Group;
|
||||
import com.songoda.epicenchants.objects.Placeholder;
|
||||
import com.songoda.epicenchants.utils.objects.FastInv;
|
||||
import com.songoda.epicenchants.utils.objects.ItemBuilder;
|
||||
import com.songoda.epicenchants.utils.single.GeneralUtils;
|
||||
import de.tr7zw.itemnbtapi.NBTItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.songoda.epicenchants.objects.Placeholder.of;
|
||||
import static com.songoda.epicenchants.utils.single.Experience.*;
|
||||
import static com.songoda.epicenchants.utils.single.GeneralUtils.*;
|
||||
|
||||
public class AlchemistMenu extends FastInv {
|
||||
private final EpicEnchants instance;
|
||||
private final FileConfiguration config;
|
||||
private final int LEFT_SLOT, RIGHT_SLOT, PREVIEW_SLOT, ACCEPT_SLOT;
|
||||
private final ItemStack PREVIEW_ITEM, ACCEPT_ITEM;
|
||||
|
||||
public AlchemistMenu(EpicEnchants instance, FileConfiguration config) {
|
||||
super(config.getInt("rows") * 9, color(config.getString("title")));
|
||||
|
||||
this.instance = instance;
|
||||
this.config = config;
|
||||
|
||||
LEFT_SLOT = config.getInt("left-slot");
|
||||
RIGHT_SLOT = config.getInt("right-slot");
|
||||
PREVIEW_SLOT = config.getInt("preview-slot");
|
||||
ACCEPT_SLOT = config.getInt("accept-slot");
|
||||
|
||||
PREVIEW_ITEM = new ItemBuilder(config.getConfigurationSection("contents.preview")).build();
|
||||
ACCEPT_ITEM = new ItemBuilder(config.getConfigurationSection("contents.accept-before")).build();
|
||||
|
||||
if (config.isConfigurationSection("fill")) {
|
||||
fill(new ItemBuilder(config.getConfigurationSection("fill")).build());
|
||||
}
|
||||
|
||||
Set<String> filter = new HashSet<String>() {{
|
||||
add("preview");
|
||||
add("accept-before");
|
||||
add("accept-after");
|
||||
}};
|
||||
|
||||
config.getConfigurationSection("contents").getKeys(false)
|
||||
.stream()
|
||||
.filter(s -> !filter.contains(s))
|
||||
.map(s -> "contents." + s)
|
||||
.map(config::getConfigurationSection)
|
||||
.forEach(section -> {
|
||||
addItem(getSlots(config.getString("slot")), new ItemBuilder(section).build(), event -> {
|
||||
if (section.getName().equalsIgnoreCase("left-item") || section.getName().equalsIgnoreCase("right-item")) {
|
||||
if (getInventory().getItem(event.getSlot()) != null && getInventory().getItem(event.getSlot()).getType() != Material.AIR) {
|
||||
event.getPlayer().getInventory().addItem(getInventory().getItem(event.getSlot()));
|
||||
getInventory().clear(event.getSlot());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
.forEach(section -> addItem(getSlots(config.getString("slot")), new ItemBuilder(section).build()));
|
||||
|
||||
clear(RIGHT_SLOT);
|
||||
clear(LEFT_SLOT);
|
||||
|
||||
updateSlots();
|
||||
|
||||
// Player clicked an item in tinkerer
|
||||
onClick(event -> {
|
||||
if (event.getEvent().getClickedInventory() == null && event.getInventory().equals(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int slot = event.getSlot();
|
||||
|
||||
if (slot != RIGHT_SLOT && slot != LEFT_SLOT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getInventory().getItem(slot) != null && getInventory().getItem(slot).getType() != Material.AIR) {
|
||||
event.getPlayer().getInventory().addItem(getInventory().getItem(slot));
|
||||
getInventory().clear(slot);
|
||||
updateSlots();
|
||||
}
|
||||
});
|
||||
|
||||
// Player clicked his own inv
|
||||
onClick(event -> {
|
||||
if (event.getEvent().getClickedInventory() == null || event.getEvent().getClickedInventory().getType() != InventoryType.PLAYER) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getItem();
|
||||
|
||||
if (!handleItem(event.getPlayer(), itemStack)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemStack.getAmount() > 1) {
|
||||
itemStack.setAmount(itemStack.getAmount() - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
event.getEvent().getClickedInventory().clear(event.getEvent().getSlot());
|
||||
});
|
||||
|
||||
// Player closed inventory
|
||||
onClose(event -> {
|
||||
if (getInventory().getItem(RIGHT_SLOT) != null)
|
||||
event.getPlayer().getInventory().addItem(getInventory().getItem(RIGHT_SLOT));
|
||||
if (getInventory().getItem(LEFT_SLOT) != null)
|
||||
event.getPlayer().getInventory().addItem(getInventory().getItem(LEFT_SLOT));
|
||||
});
|
||||
}
|
||||
|
||||
private boolean handleItem(Player player, ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemStack toHandle = itemStack.clone();
|
||||
toHandle.setAmount(1);
|
||||
|
||||
NBTItem nbtItem = new NBTItem(toHandle);
|
||||
|
||||
if (!nbtItem.hasKey("book-item") && !nbtItem.hasKey("dust")) {
|
||||
instance.getAction().perform(player, "alchemist.not-interested");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Both slots occupied
|
||||
if (getInventory().getItem(LEFT_SLOT) != null && getInventory().getItem(RIGHT_SLOT) != null) {
|
||||
instance.getAction().perform(player, "alchemist.max-two-items");
|
||||
return false;
|
||||
}
|
||||
|
||||
int successRate = nbtItem.getInteger("success-rate");
|
||||
|
||||
// Both slots empty
|
||||
if (getInventory().getItem(LEFT_SLOT) == null && getInventory().getItem(RIGHT_SLOT) == null) {
|
||||
if (nbtItem.hasKey("book-item")) {
|
||||
Enchant enchant = instance.getEnchantManager().getValue(nbtItem.getString("enchant")).orElseThrow(() -> new IllegalStateException("Book without enchant!"));
|
||||
int level = nbtItem.getInteger("level");
|
||||
|
||||
if (enchant.getMaxLevel() == level) {
|
||||
instance.getAction().perform(player, "alchemist.max-level-book");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Group group = instance.getGroupManager().getValue(nbtItem.getString("group")).orElseThrow(() -> new IllegalStateException("Dust without group!"));
|
||||
|
||||
if (group.getOrder() == instance.getGroupManager().getValues().stream().mapToInt(Group::getOrder).max().orElse(0) || successRate == 100) {
|
||||
instance.getAction().perform(player, "alchemist." + (successRate == 100 ? "max-percentage-dust" : "highest-group-dust"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
getInventory().setItem(LEFT_SLOT, toHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
NBTItem other = new NBTItem(getInventory().getItem(getInventory().getItem(LEFT_SLOT) == null ? RIGHT_SLOT : LEFT_SLOT));
|
||||
int emptySlot = getInventory().getItem(LEFT_SLOT) == null ? LEFT_SLOT : RIGHT_SLOT;
|
||||
|
||||
if (other.hasKey("book-item")) {
|
||||
if (!nbtItem.getString("enchant").equals(other.getString("enchant"))) {
|
||||
instance.getAction().perform(player, "alchemist.different-enchantment");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nbtItem.getInteger("level").equals(other.getInteger("level"))) {
|
||||
instance.getAction().perform(player, "alchemist.different-levels");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!nbtItem.getString("group").equals(other.getString("group"))) {
|
||||
instance.getAction().perform(player, "alchemist.different-groups");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (successRate == 100) {
|
||||
instance.getAction().perform(player, "alchemist.max-percentage-dust");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
getInventory().setItem(emptySlot, toHandle);
|
||||
updateSlots();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateSlots() {
|
||||
if (getInventory().getItem(LEFT_SLOT) == null || getInventory().getItem(RIGHT_SLOT) == null) {
|
||||
addItem(ACCEPT_SLOT, ACCEPT_ITEM);
|
||||
addItem(PREVIEW_SLOT, PREVIEW_ITEM);
|
||||
return;
|
||||
}
|
||||
|
||||
NBTItem leftItem = new NBTItem(getInventory().getItem(LEFT_SLOT));
|
||||
NBTItem rightItem = new NBTItem(getInventory().getItem(RIGHT_SLOT));
|
||||
int ecoCost;
|
||||
int expCost;
|
||||
|
||||
if (leftItem.hasKey("book-item")) {
|
||||
int level = leftItem.getInteger("level");
|
||||
Enchant enchant = instance.getEnchantManager().getValue(leftItem.getString("enchant")).orElseThrow(() -> new IllegalStateException("Book without enchant!"));
|
||||
int leftSuccess = leftItem.getInteger("success-rate");
|
||||
int rightSuccess = rightItem.getInteger("success-rate");
|
||||
int leftDestroy = leftItem.getInteger("destroy-rate");
|
||||
int rightDestroy = rightItem.getInteger("destroy-rate");
|
||||
|
||||
Placeholder[] placeholders = new Placeholder[]{
|
||||
of("left_success_rate", leftSuccess),
|
||||
of("right_success_rate", rightSuccess),
|
||||
of("left_destroy_rate", leftDestroy),
|
||||
of("right_destroy_rate", rightDestroy),
|
||||
of("max_destroy_rate", Math.max(leftDestroy, rightDestroy)),
|
||||
of("min_destroy_rate", Math.min(leftDestroy, rightDestroy)),
|
||||
of("max_success_rate", Math.max(leftSuccess, rightSuccess)),
|
||||
of("min_success_rate", Math.min(leftSuccess, rightSuccess))
|
||||
};
|
||||
|
||||
int successRate = getFromFormula("book.success-rate-formula", placeholders);
|
||||
int destroyRate = getFromFormula("book.destroy-rate-formula", placeholders);
|
||||
|
||||
Placeholder[] costPlaceholders = new Placeholder[]{
|
||||
of("group_order_index", enchant.getGroup().getOrder()),
|
||||
of("final_success_rate", successRate),
|
||||
of("final_destroy_rate", destroyRate),
|
||||
};
|
||||
|
||||
ecoCost = getFromFormula("book.eco-cost-formula", costPlaceholders);
|
||||
expCost = getFromFormula("book.exp-cost-formula", costPlaceholders);
|
||||
|
||||
getInventory().setItem(PREVIEW_SLOT, enchant.getBook().get(enchant, level + 1, successRate, destroyRate));
|
||||
} else {
|
||||
Group group = instance.getGroupManager().getValue(leftItem.getString("group")).orElseThrow(() -> new IllegalStateException("Dust without group!"));
|
||||
|
||||
Placeholder[] placeholders = new Placeholder[]{
|
||||
of("left_percentage", leftItem.getInteger("percentage")),
|
||||
of("right_percentage", rightItem.getInteger("percentage"))
|
||||
};
|
||||
|
||||
int successRate = getFromFormula("dust.percentage-formula", placeholders);
|
||||
|
||||
Placeholder[] costPlaceholders = new Placeholder[]{
|
||||
of("group_order_index", group.getOrder()),
|
||||
of("final_success_rate", successRate),
|
||||
};
|
||||
|
||||
ecoCost = getFromFormula("dust.eco-cost-formula", costPlaceholders);
|
||||
expCost = getFromFormula("dust.exp-cost-formula", costPlaceholders);
|
||||
|
||||
Group newGroup = instance.getGroupManager().getValues().stream()
|
||||
.filter(s -> s.getOrder() == group.getOrder() + 1)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException("No group higher than: " + group.getIdentifier()));
|
||||
|
||||
getInventory().setItem(PREVIEW_SLOT, instance.getSpecialItems().getDust(newGroup, "magic", successRate, true));
|
||||
}
|
||||
|
||||
addItem(ACCEPT_SLOT, new ItemBuilder(config.getConfigurationSection("contents.accept-after"),
|
||||
of("eco_cost", ecoCost),
|
||||
of("exp_cost", expCost)
|
||||
).build(), event -> {
|
||||
if (!instance.getEconomy().has(event.getPlayer(), ecoCost) || getExp(event.getPlayer()) < expCost) {
|
||||
instance.getAction().perform(event.getPlayer(), "alchemist.cannot-afford");
|
||||
return;
|
||||
}
|
||||
|
||||
instance.getEconomy().withdrawPlayer(event.getPlayer(), ecoCost);
|
||||
changeExp(event.getPlayer(), -expCost);
|
||||
instance.getAction().perform(event.getPlayer(), "alchemist.success", of("eco_cost", ecoCost), of("exp_cost", expCost));
|
||||
|
||||
event.getPlayer().getInventory().addItem(getInventory().getItem(PREVIEW_SLOT));
|
||||
clear(RIGHT_SLOT);
|
||||
clear(LEFT_SLOT);
|
||||
event.getPlayer().closeInventory();
|
||||
});
|
||||
}
|
||||
|
||||
private int getFromFormula(String path, Placeholder... placeholders) {
|
||||
String toTest = config.getString(path);
|
||||
|
||||
for (Placeholder placeholder : placeholders)
|
||||
toTest = toTest.replace(placeholder.getPlaceholder(), placeholder.getToReplace().toString());
|
||||
|
||||
return (int) GeneralUtils.parseJS(toTest, "alchemist expression", 0);
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ public class EnchanterMenu extends FastInv {
|
||||
.map(s -> "contents." + s)
|
||||
.map(config::getConfigurationSection)
|
||||
.forEach(section -> {
|
||||
double expCost = section.getDouble("exp-cost");
|
||||
double ecoCost = section.getDouble("eco-cost");
|
||||
double xpLeft = expCost - player.getLevel() < 0 ? 0 : expCost - player.getLevel();
|
||||
int expCost = section.getInt("exp-cost");
|
||||
int ecoCost = section.getInt("eco-cost");
|
||||
int xpLeft = expCost - player.getLevel() < 0 ? 0 : expCost - player.getLevel();
|
||||
double ecoLeft = ecoCost - instance.getEconomy().getBalance(player) < 0 ? 0 : ecoCost - instance.getEconomy().getBalance(player);
|
||||
Group group = instance.getGroupManager().getValue(section.getString("group").toUpperCase())
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid group set in enchanter: " + section.getString("group")));
|
||||
@ -50,7 +50,7 @@ public class EnchanterMenu extends FastInv {
|
||||
of("eco_cost", ecoCost),
|
||||
of("exp_cost", expCost));
|
||||
|
||||
changeExp(player, (int) -expCost);
|
||||
changeExp(player, -expCost);
|
||||
player.getInventory().addItem(instance.getSpecialItems().getMysteryBook(group));
|
||||
});
|
||||
});
|
||||
|
@ -5,10 +5,11 @@ import com.songoda.epicenchants.objects.Group;
|
||||
import com.songoda.epicenchants.utils.objects.FastInv;
|
||||
import com.songoda.epicenchants.utils.objects.ItemBuilder;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import static com.songoda.epicenchants.utils.single.GeneralUtils.color;
|
||||
|
||||
public class MainInfoMenu extends FastInv {
|
||||
public class MainInfoMenu extends FastInv implements Listener {
|
||||
|
||||
public MainInfoMenu(EpicEnchants instance, FileConfiguration config) {
|
||||
super(config.getInt("rows") * 9, color(config.getString("title")));
|
||||
@ -25,4 +26,5 @@ public class MainInfoMenu extends FastInv {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -51,9 +51,9 @@ public class TinkererMenu extends FastInv {
|
||||
if (section.getName().equalsIgnoreCase("accept-left") || section.getName().equalsIgnoreCase("accept-right")) {
|
||||
slotMap.values().stream().map(slot -> getInventory().getItem(slot)).filter(Objects::nonNull).forEach(event.getPlayer().getInventory()::addItem);
|
||||
slotMap.keySet().forEach(slot -> getInventory().clear(slot));
|
||||
accepted.set(true);
|
||||
event.getPlayer().closeInventory();
|
||||
instance.getAction().perform(event.getPlayer(), "tinkerer.accepted");
|
||||
accepted.set(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ public class TinkererMenu extends FastInv {
|
||||
|
||||
// Player clicked an item in tinkerer
|
||||
onClick(event -> {
|
||||
if (event.getEvent().getClickedInventory() == null) {
|
||||
if (event.getEvent().getClickedInventory() == null && event.getInventory().equals(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,13 @@
|
||||
package com.songoda.epicenchants.objects;
|
||||
|
||||
import com.songoda.epicenchants.utils.single.GeneralUtils;
|
||||
import com.songoda.epicenchants.utils.single.Placeholders;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public class Condition {
|
||||
private final String string;
|
||||
|
||||
@ -28,17 +24,8 @@ public class Condition {
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
|
||||
String toValidate = ChatColor.stripColor(Placeholders.setPlaceholders(string, user, attacker, level, event));
|
||||
|
||||
System.out.println("Verifying: " + toValidate);
|
||||
|
||||
try {
|
||||
return Boolean.parseBoolean(scriptEngine.eval(toValidate).toString());
|
||||
} catch (ScriptException ignore) {
|
||||
Bukkit.getLogger().warning("[EpicEnchants] One of your condition expressions is not properly formatted.");
|
||||
Bukkit.getLogger().warning(toValidate);
|
||||
return def;
|
||||
}
|
||||
return (boolean) GeneralUtils.parseJS(toValidate, "condition", def);
|
||||
}
|
||||
}
|
||||
|
@ -14,4 +14,5 @@ public class Group {
|
||||
private BookItem bookItem;
|
||||
private int destroyRateMin, destroyRateMax, successRateMin, successRateMax;
|
||||
private int tinkererExp;
|
||||
private int order;
|
||||
}
|
||||
|
@ -1,14 +1,10 @@
|
||||
package com.songoda.epicenchants.objects;
|
||||
|
||||
import com.songoda.epicenchants.utils.single.GeneralUtils;
|
||||
import com.songoda.epicenchants.utils.single.Placeholders;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public class LeveledModifier {
|
||||
private final String string;
|
||||
|
||||
@ -29,15 +25,8 @@ public class LeveledModifier {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
|
||||
String toTest = Placeholders.setPlaceholders(string, user, opponent, level);
|
||||
|
||||
try {
|
||||
return Double.parseDouble(scriptEngine.eval(toTest).toString());
|
||||
} catch (ScriptException | NumberFormatException e) {
|
||||
Bukkit.getLogger().warning("[EpicEnchants] One of your math expressions is not properly formatted.");
|
||||
Bukkit.getLogger().warning(toTest);
|
||||
return def;
|
||||
}
|
||||
return (double) GeneralUtils.parseJS(toTest, "LeveledModifier", def);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class EnchantUtils {
|
||||
return Pair.of(itemStack, MAXED_OUT);
|
||||
}
|
||||
|
||||
if (currentEnchantMap.entrySet().stream().anyMatch(entry -> entry.getKey().equals(enchant) && entry.getValue() == level)) {
|
||||
if (currentEnchantMap.entrySet().stream().anyMatch(entry -> entry.getKey().equals(enchant) && entry.getValue() >= level)) {
|
||||
return Pair.of(itemStack, ALREADY_APPLIED);
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ public class EnchantUtils {
|
||||
|
||||
public void handlePlayer(@NotNull Player player, @Nullable LivingEntity opponent, Event event, TriggerType triggerType) {
|
||||
List<ItemStack> stacks = new ArrayList<>(Arrays.asList(player.getInventory().getArmorContents()));
|
||||
stacks.add(player.getItemInHand());
|
||||
stacks.add(GeneralUtils.getHeldItem(player, event));
|
||||
stacks.removeIf(Objects::isNull);
|
||||
|
||||
if (triggerType == HELD_ITEM) {
|
||||
|
@ -123,6 +123,6 @@ public class SpecialItems {
|
||||
}
|
||||
|
||||
public String getWhiteScrollLore() {
|
||||
return color(instance.getFileManager().getConfiguration("special-items").getConfigurationSection("white-scroll").getString("format"));
|
||||
return color(instance.getFileManager().getConfiguration("items/special-items").getString("white-scroll.format"));
|
||||
}
|
||||
}
|
||||
|
@ -31,15 +31,6 @@ public class FastInv implements InventoryHolder {
|
||||
private final Map<Integer, FastInvClickListener> itemListeners = new HashMap<>();
|
||||
private final Set<BukkitTask> tasks = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Create a new FastInv with a custom size.
|
||||
*
|
||||
* @param size The size of the menus.
|
||||
*/
|
||||
public FastInv(int size) {
|
||||
this(size, InventoryType.CHEST.getDefaultTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FastInv with a custom size and title.
|
||||
*
|
||||
@ -50,26 +41,6 @@ public class FastInv implements InventoryHolder {
|
||||
this(size, InventoryType.CHEST, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FastInv with a custom type.
|
||||
*
|
||||
* @param type The type of the menus.
|
||||
*/
|
||||
public FastInv(InventoryType type) {
|
||||
this(type, type.getDefaultTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FastInv with a custom type and title.
|
||||
*
|
||||
* @param type The type of the menus.
|
||||
* @param title The title of the menus.
|
||||
* @throws IllegalStateException if FastInv is not init with FastInv.init(Plugin plugin)
|
||||
*/
|
||||
public FastInv(InventoryType type, String title) {
|
||||
this(0, type, title);
|
||||
}
|
||||
|
||||
private FastInv(int size, InventoryType type, String title) {
|
||||
if (plugin == null) {
|
||||
throw new IllegalStateException("FastInv is not initialised");
|
||||
@ -249,6 +220,16 @@ public class FastInv implements InventoryHolder {
|
||||
return addItem(slots, item, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a spot in the inventory.
|
||||
*
|
||||
* @param slot The slot to clear.
|
||||
* @return This FastInv instance, for chaining.
|
||||
*/
|
||||
public FastInv clear(int slot) {
|
||||
return addItem(slot, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an {@link ItemStack} to the menus on the edges.
|
||||
*
|
||||
@ -350,19 +331,6 @@ public class FastInv implements InventoryHolder {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> player.openInventory(inventory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the menus to players.
|
||||
*
|
||||
* @param players The players to open the menu.
|
||||
*/
|
||||
public void open(Player... players) {
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
for (Player p : players) {
|
||||
p.openInventory(inventory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all tasks.
|
||||
*/
|
||||
|
@ -3,10 +3,7 @@ package com.songoda.epicenchants.utils.single;
|
||||
import com.songoda.epicenchants.EpicEnchants;
|
||||
import com.songoda.epicenchants.effect.EffectManager;
|
||||
import com.songoda.epicenchants.enums.TriggerType;
|
||||
import com.songoda.epicenchants.objects.BookItem;
|
||||
import com.songoda.epicenchants.objects.Enchant;
|
||||
import com.songoda.epicenchants.objects.Group;
|
||||
import com.songoda.epicenchants.objects.LeveledModifier;
|
||||
import com.songoda.epicenchants.objects.*;
|
||||
import com.songoda.epicenchants.utils.objects.ItemBuilder;
|
||||
import com.songoda.epicenchants.wrappers.EnchantmentWrapper;
|
||||
import com.songoda.epicenchants.wrappers.MobWrapper;
|
||||
@ -16,10 +13,7 @@ import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.songoda.epicenchants.utils.single.GeneralUtils.color;
|
||||
@ -86,6 +80,7 @@ public class ConfigParser {
|
||||
|
||||
public static Group parseGroup(EpicEnchants instance, ConfigurationSection section) {
|
||||
return section != null ? Group.builder()
|
||||
.order(section.getInt("order"))
|
||||
.identifier(section.getName())
|
||||
.name(color(section.getString("group-name")))
|
||||
.format(section.getString("group-lore-format"))
|
||||
|
@ -3,15 +3,25 @@ package com.songoda.epicenchants.utils.single;
|
||||
import com.songoda.epicenchants.enums.EnchantResult;
|
||||
import com.songoda.epicenchants.enums.TriggerType;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GeneralUtils {
|
||||
private static final ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("JavaScript");
|
||||
|
||||
public static boolean chance(int chance) {
|
||||
return chance((double) chance);
|
||||
}
|
||||
@ -24,6 +34,10 @@ public class GeneralUtils {
|
||||
return format(input, "", null);
|
||||
}
|
||||
|
||||
public static List<String> getString(ConfigurationSection section, String path) {
|
||||
return section.isList(path) ? section.getStringList(path) : Collections.singletonList(section.getString(path));
|
||||
}
|
||||
|
||||
public static String format(String input, String placeholder, Object toReplace) {
|
||||
return ChatColor.translateAlternateColorCodes('&', input).replaceAll(placeholder, toReplace == null ? "" : toReplace.toString());
|
||||
}
|
||||
@ -47,11 +61,31 @@ public class GeneralUtils {
|
||||
return Arrays.stream(string.split(",")).filter(StringUtils::isNumeric).mapToInt(Integer::parseInt).toArray();
|
||||
}
|
||||
|
||||
public static List<Integer> getSlotsList(String string) {
|
||||
return Arrays.stream(string.split(",")).filter(StringUtils::isNumeric).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Set<TriggerType> parseTrigger(String triggers) {
|
||||
return Arrays.stream(triggers.replaceAll("\\s+", "").split(",")).map(TriggerType::valueOf).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static ItemStack getHeldItem(Player player, Event event) {
|
||||
int slot = player.getInventory().getHeldItemSlot();
|
||||
|
||||
try {
|
||||
if (event instanceof PlayerInteractEvent && ((PlayerInteractEvent) event).getHand() == EquipmentSlot.OFF_HAND) {
|
||||
slot = 40;
|
||||
}
|
||||
} catch (NoSuchMethodError ignore) {
|
||||
}
|
||||
|
||||
return player.getInventory().getItem(slot);
|
||||
}
|
||||
|
||||
public static Object parseJS(String toParse, String type, Object def) {
|
||||
|
||||
try {
|
||||
return SCRIPT_ENGINE.eval(toParse);
|
||||
} catch (ScriptException | NumberFormatException e) {
|
||||
Bukkit.getLogger().warning("[EpicEnchants] One of your " + type + " expressions is not properly formatted.");
|
||||
Bukkit.getLogger().warning(toParse);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.songoda.epicenchants.utils.single;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
@ -9,13 +10,19 @@ import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.songoda.epicenchants.utils.single.GeneralUtils.getHeldItem;
|
||||
|
||||
public class Placeholders {
|
||||
|
||||
@ -25,29 +32,57 @@ public class Placeholders {
|
||||
return ((BlockBreakEvent) event).getBlock().getType().toString();
|
||||
} else if (event instanceof BlockPlaceEvent) {
|
||||
return ((BlockPlaceEvent) event).getBlockPlaced().getType().toString();
|
||||
} else if (event instanceof PlayerInteractEvent && ((PlayerInteractEvent) event).hasBlock()) {
|
||||
return ((PlayerInteractEvent) event).getClickedBlock().getType().toString();
|
||||
} else return "N/A";
|
||||
});
|
||||
|
||||
put("{clicked_type}", event -> {
|
||||
if (event instanceof PlayerInteractEvent && ((PlayerInteractEvent) event).hasBlock()) {
|
||||
return ((PlayerInteractEvent) event).getClickedBlock().getType().toString();
|
||||
} else if (event instanceof PlayerInteractEntityEvent) {
|
||||
if (event instanceof PlayerInteractEntityEvent) {
|
||||
return ((PlayerInteractEntityEvent) event).getRightClicked().getType().toString();
|
||||
} else return "N/A";
|
||||
});
|
||||
}};
|
||||
|
||||
private static final Map<String, BiFunction<Player, LivingEntity, Object>> PLAYER_FUNCTIONS = new HashMap<String, BiFunction<Player, LivingEntity, Object>>() {{
|
||||
put("{user_name}", (user, opponent) -> user.getName());
|
||||
put("{opponent_name}", (user, opponent) -> opponent == null ? "" : opponent.getName());
|
||||
|
||||
put("{user_health}", (user, opponent) -> user.getHealth());
|
||||
put("{attacker_health}", (user, opponent) -> opponent == null ? -1 : opponent.getHealth());
|
||||
put("{opponent_health}", (user, opponent) -> opponent == null ? -1 : opponent.getHealth());
|
||||
|
||||
put("{user_food}", (user, opponent) -> user.getFoodLevel());
|
||||
put("{attacker_food}", (user, opponent) -> opponent instanceof Player ? ((Player) opponent).getFoodLevel() : 0);
|
||||
put("{opponent_food}", (user, opponent) -> opponent instanceof Player ? ((Player) opponent).getFoodLevel() : 0);
|
||||
|
||||
put("{user_is_sneaking}", (user, opponent) -> user.isSneaking());
|
||||
put("{attacker_is_sneaking}", (user, opponent) -> opponent instanceof Player && ((Player) opponent).isSneaking());
|
||||
put("{opponent_is_sneaking}", (user, opponent) -> opponent instanceof Player && ((Player) opponent).isSneaking());
|
||||
|
||||
put("{user_holding}", (user, opponent) -> Optional.ofNullable(getHeldItem(user, null)).map(ItemStack::getType).orElse(Material.AIR));
|
||||
put("{opponent_holding}", (user, opponent) -> opponent instanceof Player ? Optional.ofNullable(getHeldItem((Player) opponent, null)).map(ItemStack::getType).orElse(Material.AIR) : "N/A");
|
||||
|
||||
put("{user_is_swimming}", (user, opponent) -> user.getLocation().getBlock().isLiquid());
|
||||
put("{opponent_is_swimming}", (user, opponent) -> opponent != null && opponent.getLocation().getBlock().isLiquid());
|
||||
|
||||
put("{world}", (user, opponent) -> user.getWorld().getName());
|
||||
put("{players_near}", (user, opponent) -> user.getNearbyEntities(4, 4, 4).size());
|
||||
put("{user_on_fire}", (user, opponent) -> user.getFireTicks() != 0);
|
||||
put("{attacker_on_fire}", (user, opponent) -> opponent != null && opponent.getFireTicks() != 0);
|
||||
put("{opponent_on_fire}", (user, opponent) -> opponent != null && opponent.getFireTicks() != 0);
|
||||
}};
|
||||
|
||||
private static final Set<Consumer<AtomicReference<String>>> REGEX_CONSUMERS = new HashSet<Consumer<AtomicReference<String>>>() {{
|
||||
add(reference -> {
|
||||
Pattern pattern = Pattern.compile("\\{random\\((.*)\\)}");
|
||||
Matcher matcher = pattern.matcher(reference.get());
|
||||
|
||||
if (!matcher.find()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Integer> args = Arrays.stream(matcher.group(1).replaceAll("/\\s/g", "").split(","))
|
||||
.collect(Collectors.toMap(s -> s.split("=")[0], s -> Integer.parseInt(s.split("=")[1])));
|
||||
|
||||
reference.getAndUpdate(s -> s.replaceAll(pattern.pattern(), "" + ThreadLocalRandom.current().nextInt(args.get("low"), args.get("up"))));
|
||||
});
|
||||
}};
|
||||
|
||||
public static String setPlaceholders(String input, Player user, LivingEntity opponent, int level) {
|
||||
@ -58,7 +93,8 @@ public class Placeholders {
|
||||
AtomicReference<String> output = new AtomicReference<>(input.replace("{level}", "" + level));
|
||||
|
||||
PLAYER_FUNCTIONS.forEach((toReplace, function) -> output.updateAndGet(string -> string.replace(toReplace, function.apply(user, opponent).toString())));
|
||||
Optional.ofNullable(event).ifPresent(e -> EVENT_FUNCTIONS.forEach((toReplace, function) -> output.updateAndGet(string -> "'" + string.replace(toReplace, function.apply(e)) + "'")));
|
||||
REGEX_CONSUMERS.forEach(consumer -> consumer.accept(output));
|
||||
Optional.ofNullable(event).ifPresent(e -> EVENT_FUNCTIONS.forEach((toReplace, function) -> output.updateAndGet(string -> string.replace(toReplace, "'" + function.apply(e) + "'"))));
|
||||
|
||||
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
|
||||
output.updateAndGet(string -> PlaceholderAPI.setPlaceholders(user, string));
|
||||
@ -70,4 +106,6 @@ public class Placeholders {
|
||||
|
||||
return output.get();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ public class RomanNumber {
|
||||
return map.get(number);
|
||||
}
|
||||
return map.get(l) + toRoman(number - l);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
general:
|
||||
prefix: "&8[&6EpicEnchants&8]"
|
||||
no-permission: "&cYou do not have permission to do that."
|
||||
|
||||
command:
|
||||
@ -15,23 +14,35 @@ command:
|
||||
reload: "&6Configuration files reload"
|
||||
|
||||
enchanter:
|
||||
cannot-afford: "&cYou cannot afford this purchase."
|
||||
cannot-afford: "&c&l(!) &r&cYou cannot afford this purchase."
|
||||
success: "&7Purchased {group_color}{group_name} &7book for &f{exp_cost} EXP&7."
|
||||
|
||||
tinkerer:
|
||||
open: "&eTrading with the tinkerer."
|
||||
cancelled: "&cCancelled."
|
||||
cancelled: "&c&l(!) &r&cCancelled."
|
||||
accepted: "&aAccepted"
|
||||
no-items: "&c&l(!) &r&cThe tinkerer is not interested in any of your items!"
|
||||
deposited-all: "&a&l(!) &r&aDeposited {amount} items."
|
||||
|
||||
alchemist:
|
||||
max-two-items: "&c&l(!) &r&cYou may only combine 2 items at once."
|
||||
not-interested: "&c&l(!) &r&cThe alchemist is not interested in any of your items!"
|
||||
max-level-book: "&c&l(!) &r&cThe alchemist cannot combine max level books."
|
||||
max-percentage-dust: "&c&l(!) &r&cThe alchemist cannot combine 100% success rate dusts."
|
||||
highest-group-dust: "&c&l(!) &r&cThe alchemist can't accept dust of the highest tier."
|
||||
different-enchantment: "&c&l(!) &r&cThe alchemist can only combine books with the same enchantment."
|
||||
different-levels: "&c&l(!) &r&cThe alchemist can only combine books of the same level."
|
||||
different-groups: "&c&l(!) &r&cThe alchemist can only combine dusts of the same group."
|
||||
cannot-afford: "&c&l(!) You cannot afford this exchange."
|
||||
success: "&7Exchanged for &f{exp_cost} EXP&7."
|
||||
|
||||
enchants:
|
||||
invalid-material: "&cYou can not apply &6{enchant} &cto that item."
|
||||
broken-failure: "&6{enchant} &cfailed to apply and broke your item..."
|
||||
success: "&aYou have success fully applied &6{enchant}."
|
||||
conflict: "&cYou cannot apply this enchant as it conflicts with another enchant."
|
||||
maxed-out: "&cYou already have that enchant maxed on this item."
|
||||
already-applied: "&cYou already have that enchant with that level applied on this item."
|
||||
already-applied: "&cYou already have that enchant applied on this item."
|
||||
protected: "&aYour book would have broken your item, luckily it was protected!"
|
||||
|
||||
book:
|
||||
|
@ -1,5 +1,6 @@
|
||||
groups:
|
||||
SIMPLE:
|
||||
order: 0
|
||||
group-color: "&f"
|
||||
group-name: "Simple"
|
||||
group-lore-format: "{group_color}{enchant} {level}"
|
||||
@ -18,6 +19,7 @@ groups:
|
||||
- "&7{item_group} Enchantment"
|
||||
- "&7Drag and drop to enchant."
|
||||
UNIQUE:
|
||||
order: 1
|
||||
group-color: "&a"
|
||||
group-name: "Unique"
|
||||
group-lore-format: "{group_color}{enchant} {level}"
|
||||
@ -36,6 +38,7 @@ groups:
|
||||
- "&7{item_group} Enchantment"
|
||||
- "&7Drag and drop to enchant."
|
||||
ELITE:
|
||||
order: 2
|
||||
group-color: "&b"
|
||||
group-name: "Elite"
|
||||
group-lore-format: "{group_color}{enchant} {level}"
|
||||
@ -54,6 +57,7 @@ groups:
|
||||
- "&7{item_group} Enchantment"
|
||||
- "&7Drag and drop to enchant."
|
||||
ULTIMATE:
|
||||
order: 3
|
||||
group-color: "&e"
|
||||
group-name: "Ultimate"
|
||||
group-lore-format: "{group_color}{enchant} {level}"
|
||||
@ -72,6 +76,7 @@ groups:
|
||||
- "&7{item_group} Enchantment"
|
||||
- "&7Drag and drop to enchant."
|
||||
LEGENDARY:
|
||||
order: 4
|
||||
group-color: "&6"
|
||||
group-name: "Legendary"
|
||||
group-lore-format: "{group_color}{enchant} {level}"
|
||||
|
@ -8,7 +8,7 @@ white-scroll:
|
||||
- "&ePlace scroll on item to apply."
|
||||
|
||||
black-scroll:
|
||||
material: INK_SACK
|
||||
material: INC_SAC
|
||||
display-name: "&f&lBlack Scroll"
|
||||
lore:
|
||||
- "&7Removes a random enchantment"
|
||||
|
@ -0,0 +1,53 @@
|
||||
title: "Alchemist"
|
||||
rows: 3
|
||||
|
||||
fill:
|
||||
material: STAINED_GLASS_PANE
|
||||
data: 7
|
||||
display-name: "&r"
|
||||
|
||||
left-slot: 3
|
||||
right-slot: 5
|
||||
preview-slot: 13
|
||||
accept-slot: 22
|
||||
|
||||
book:
|
||||
success-rate-formula: "({left_success_rate} + {right_success_rate}) / 4"
|
||||
destroy-rate-formula: "({left_destroy_rate} + {right_destroy_rate}) / 4 + {max_destroy_rate}"
|
||||
eco-cost-formula: "0"
|
||||
exp-cost-formula: "({group_order_index} + 1) * {final_success_rate}"
|
||||
|
||||
dust:
|
||||
percentage-formula: "({left_percentage} + {right_percentage}) / 2"
|
||||
eco-cost-formula: "0"
|
||||
exp-cost-formula: "({group_order_index} + 1) * {final_success_rate}"
|
||||
|
||||
contents:
|
||||
preview:
|
||||
material: STAINED_GLASS_PANE
|
||||
display-name: "&eITEM PREVIEW"
|
||||
lore:
|
||||
- "&7A preview of the item that you"
|
||||
- "&7will receive from the alchemist"
|
||||
- "&7will be displayed here."
|
||||
accept-before:
|
||||
material: STAINED_GLASS_PANE
|
||||
data: 14
|
||||
display-name: "&8[&eThe Alchemist&8]"
|
||||
lore:
|
||||
- "&7You will exchange"
|
||||
- ""
|
||||
- "&8- &f2x enchantment books"
|
||||
- "&7(of the same type and level) &ffor"
|
||||
- "&fthe same enchantment book"
|
||||
- "&7(with a higher success rate)"
|
||||
accept-after:
|
||||
material: STAINED_GLASS_PANE
|
||||
data: 5
|
||||
display-name: "&eClick to confirm"
|
||||
lore:
|
||||
- "&cCost: {exp_cost} EXP"
|
||||
- ""
|
||||
- "&7Click to confirm the exchange"
|
||||
- "&7after which you will receive"
|
||||
- "&7the item displayed above."
|
@ -0,0 +1,50 @@
|
||||
title: "Alchemist"
|
||||
rows: 3
|
||||
|
||||
fill:
|
||||
material: GRAY_STAINED_GLASS_PANE
|
||||
display-name: "&r"
|
||||
|
||||
left-slot: 3
|
||||
right-slot: 5
|
||||
preview-slot: 13
|
||||
accept-slot: 22
|
||||
|
||||
book:
|
||||
success-rate-formula: "({left_success_rate} + {right_success_rate}) / 4"
|
||||
destroy-rate-formula: "({left_destroy_rate} + {right_destroy_rate}) / 4 + {max_destroy_rate}"
|
||||
eco-cost-formula: "0"
|
||||
exp-cost-formula: "({group_order_index} + 1) * {final_success_rate}"
|
||||
|
||||
dust:
|
||||
percentage-formula: "({left_percentage} + {right_percentage}) / 2"
|
||||
eco-cost-formula: "0"
|
||||
exp-cost-formula: "({group_order_index} + 1) * {final_success_rate}"
|
||||
|
||||
contents:
|
||||
preview:
|
||||
material: WHITE_STAINED_GLASS_PANE
|
||||
display-name: "&eITEM PREVIEW"
|
||||
lore:
|
||||
- "&7A preview of the item that you"
|
||||
- "&7will receive from the alchemist"
|
||||
- "&7will be displayed here."
|
||||
accept-before:
|
||||
material: RED_STAINED_GLASS_PANE
|
||||
display-name: "&8[&eThe Alchemist&8]"
|
||||
lore:
|
||||
- "&7You will exchange"
|
||||
- ""
|
||||
- "&8- &f2x enchantment books"
|
||||
- "&7(of the same type and level) &ffor"
|
||||
- "&fthe same enchantment book"
|
||||
- "&7(with a higher success rate)"
|
||||
accept-after:
|
||||
material: LIME_STAINED_GLASS_PANE
|
||||
display-name: "&eClick to confirm"
|
||||
lore:
|
||||
- "&cCost: {exp_cost} EXP"
|
||||
- ""
|
||||
- "&7Click to confirm the exchange"
|
||||
- "&7after which you will receive"
|
||||
- "&7the item displayed above."
|
Loading…
Reference in New Issue
Block a user