EpicEnchants/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java

298 lines
13 KiB
Java

package com.songoda.epicenchants.menus;
import com.songoda.core.hooks.EconomyManager;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.nbt.NBTItem;
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 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.changeExp;
import static com.songoda.epicenchants.utils.single.Experience.getExp;
import static com.songoda.epicenchants.utils.single.GeneralUtils.color;
import static com.songoda.epicenchants.utils.single.GeneralUtils.getSlots;
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(section.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 = NmsManager.getNbt().of(toHandle);
if (!nbtItem.has("book-item") && !nbtItem.has("dust")) {
instance.getLocale().getMessage("alchemist.notinterested").sendPrefixedMessage(player);
return false;
}
// Both slots occupied
if (getInventory().getItem(LEFT_SLOT) != null && getInventory().getItem(RIGHT_SLOT) != null) {
instance.getLocale().getMessage("alchemist.maxtwoitems").sendPrefixedMessage(player);
return false;
}
int successRate = nbtItem.getNBTObject("success-rate").asInt();
// Both slots empty
if (getInventory().getItem(LEFT_SLOT) == null && getInventory().getItem(RIGHT_SLOT) == null) {
if (nbtItem.has("book-item")) {
Enchant enchant = instance.getEnchantManager().getValue(nbtItem.getNBTObject("enchant").asString()).orElseThrow(() -> new IllegalStateException("Book without enchant!"));
int level = nbtItem.getNBTObject("level").asInt();
if (enchant.getMaxLevel() == level) {
instance.getLocale().getMessage("alchemist.maxlevelbook")
.sendPrefixedMessage(player);
return false;
}
} else {
Group group = instance.getGroupManager().getValue(nbtItem.getNBTObject("group").asString()).orElseThrow(() -> new IllegalStateException("Dust without group!"));
if (group.getOrder() == instance.getGroupManager().getValues().stream().mapToInt(Group::getOrder).max().orElse(0) || successRate == 100) {
instance.getLocale().getMessage("alchemist." + (successRate == 100 ? "maxpercentagedust" : "highestgroupdust"))
.sendPrefixedMessage(player);
return false;
}
}
getInventory().setItem(LEFT_SLOT, toHandle);
return true;
}
NBTItem other = NmsManager.getNbt().of(getInventory().getItem(getInventory().getItem(LEFT_SLOT) == null ? RIGHT_SLOT : LEFT_SLOT));
int emptySlot = getInventory().getItem(LEFT_SLOT) == null ? LEFT_SLOT : RIGHT_SLOT;
if (other.has("book-item")) {
if (!nbtItem.getNBTObject("enchant").asString().equals(other.getNBTObject("enchant").asString())) {
instance.getLocale().getMessage("alchemist.differentenchantment").sendPrefixedMessage(player);
return false;
}
if (nbtItem.getNBTObject("level").asInt() != other.getNBTObject("level").asInt()) {
instance.getLocale().getMessage("alchemist.differentlevels").sendPrefixedMessage(player);
return false;
}
} else {
if (!nbtItem.getNBTObject("group").asString().equals(other.getNBTObject("group").asString())) {
instance.getLocale().getMessage("alchemist.differentgroups").sendPrefixedMessage(player);
return false;
}
if (successRate >= 100) {
instance.getLocale().getMessage("alchemist.maxpercentagedust").sendPrefixedMessage(player);
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 = NmsManager.getNbt().of(getInventory().getItem(LEFT_SLOT));
NBTItem rightItem = NmsManager.getNbt().of(getInventory().getItem(RIGHT_SLOT));
int ecoCost;
int expCost;
if (leftItem.has("book-item")) {
int level = leftItem.getNBTObject("level").asInt();
Enchant enchant = instance.getEnchantManager().getValue(leftItem.getNBTObject("enchant").asString()).orElseThrow(() -> new IllegalStateException("Book without enchant!"));
int leftSuccess = leftItem.getNBTObject("success-rate").asInt();
int rightSuccess = rightItem.getNBTObject("success-rate").asInt();
int leftDestroy = leftItem.getNBTObject("destroy-rate").asInt();
int rightDestroy = rightItem.getNBTObject("destroy-rate").asInt();
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.getNBTObject("group").asString()).orElseThrow(() -> new IllegalStateException("Dust without group!"));
Placeholder[] placeholders = new Placeholder[] {
of("left_percentage", leftItem.getNBTObject("percentage").asInt()),
of("right_percentage", rightItem.getNBTObject("percentage").asInt())
};
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 (!EconomyManager.hasBalance(event.getPlayer(), ecoCost) || getExp(event.getPlayer()) < expCost) {
instance.getLocale().getMessage("alchemist.cannotafford").sendPrefixedMessage(event.getPlayer());
return;
}
EconomyManager.withdrawBalance(event.getPlayer(), ecoCost);
changeExp(event.getPlayer(), -expCost);
instance.getLocale().getMessage("alchemist.success")
.processPlaceholder("eco_cost", ecoCost)
.processPlaceholder("exp_cost", expCost)
.sendPrefixedMessage(event.getPlayer());
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) Double.parseDouble(GeneralUtils.parseJS(toTest, "alchemist expression", 0).toString());
}
}