studio.magemonkey.divinity.modules.list.magicdust.MagicDustManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of divinity Show documentation
Show all versions of divinity Show documentation
Custom items, combat, and more!
The newest version!
package studio.magemonkey.divinity.modules.list.magicdust;
import studio.magemonkey.codex.config.api.JYML;
import studio.magemonkey.codex.hooks.external.VaultHK;
import studio.magemonkey.codex.hooks.external.citizens.CitizensHK;
import studio.magemonkey.codex.util.ItemUT;
import studio.magemonkey.codex.util.NumberUT;
import studio.magemonkey.codex.util.StringUT;
import studio.magemonkey.codex.util.actions.ActionManipulator;
import studio.magemonkey.divinity.Divinity;
import studio.magemonkey.divinity.Perms;
import studio.magemonkey.divinity.modules.EModule;
import studio.magemonkey.divinity.modules.LimitedItem;
import studio.magemonkey.divinity.modules.ModuleItem;
import studio.magemonkey.divinity.modules.RatedItem;
import studio.magemonkey.divinity.modules.api.QModuleDrop;
import studio.magemonkey.divinity.modules.list.magicdust.MagicDustManager.MagicDust;
import studio.magemonkey.divinity.modules.list.magicdust.command.DustOpenCmd;
import studio.magemonkey.divinity.modules.list.magicdust.event.PlayerImproveItemSocketRateEvent;
import studio.magemonkey.divinity.stats.items.ItemStats;
import net.citizensnpcs.api.trait.TraitInfo;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import studio.magemonkey.codex.manager.api.gui.*;
import java.util.*;
public class MagicDustManager extends QModuleDrop {
PaidGUI guiPaid;
private ActionManipulator actionsApply;
private ActionManipulator actionsError;
public MagicDustManager(@NotNull Divinity plugin) {
super(plugin, MagicDust.class);
}
@Override
@NotNull
public String getId() {
return EModule.MAGIC_DUST;
}
@Override
@NotNull
public String version() {
return "1.9.0";
}
@Override
public void setup() {
this.moduleCommand.addSubCommand(new DustOpenCmd(this));
this.actionsApply = new ActionManipulator(plugin, cfg, "general.actions-apply");
this.actionsError = new ActionManipulator(plugin, cfg, "general.actions-error");
this.guiPaid = new PaidGUI(this.plugin);
CitizensHK citizens = plugin.getCitizens();
if (citizens != null) {
TraitInfo trait = TraitInfo.create(MagicDustTrait.class).withName("magicdust");
citizens.registerTrait(plugin, trait);
}
}
@Override
public void shutdown() {
if (this.guiPaid != null) {
this.guiPaid.shutdown();
this.guiPaid = null;
}
this.actionsApply = null;
this.actionsError = null;
}
// -------------------------------------------------------------------- //
// EVENTS
@Override
protected boolean onDragDrop(
@NotNull Player player,
@NotNull ItemStack src,
@NotNull ItemStack target,
@NotNull MagicDust mDust,
@NotNull InventoryClickEvent e) {
if (!this.isRateableItem(target)) return false;
int targetRate = ItemStats.getSocketRate(target);
if (targetRate < 0) return false;
// If item success rate is above the cap.
if (targetRate >= mDust.getMaxRate()) {
plugin.lang().MagicDust_Apply_Error_MaxRate
.replace("%source%", ItemUT.getItemName(src))
.replace("%max-rate%", String.valueOf(targetRate))
.send(player);
this.actionsError.process(player);
return false;
}
int rateAdd = mDust.getRateByLevel(ItemStats.getLevel(src));
int rateFinal = targetRate + rateAdd;
PlayerImproveItemSocketRateEvent event =
new PlayerImproveItemSocketRateEvent(player, target, targetRate, rateFinal);
plugin.getPluginManager().callEvent(event);
if (event.isCancelled()) {
this.actionsError.process(player);
return false;
}
this.takeChargeClickEvent(player, src, e);
// Save other items in stack
// and then return them back to a player
ItemStack lost = null;
if (target.getAmount() > 1) {
lost = new ItemStack(target);
lost.setAmount(target.getAmount() - 1);
target.setAmount(1);
}
e.setCurrentItem(this.changeItemRate(target, rateAdd));
if (lost != null) {
ItemUT.addItem(player, lost);
}
return true;
}
@NotNull
public ItemStack changeItemRate(@NotNull ItemStack target, int toAdd) {
QModuleDrop> moduleDrop = ItemStats.getModule(target);
if (moduleDrop == null || !moduleDrop.isLoaded()) {
return target;
}
int targetRate = ItemStats.getSocketRate(target);
if (targetRate < 0) return target;
ModuleItem mItem = moduleDrop.getModuleItem(target);
if (mItem == null || !(mItem instanceof RatedItem)) return target;
RatedItem rItem = (RatedItem) mItem;
int targetLvl = ItemStats.getLevel(target);
int targetUses = moduleDrop.getItemCharges(target);
int rateFinal = Math.max(0, targetRate + toAdd);
return rItem.create(targetLvl, targetUses, rateFinal);
}
public boolean isRateableItem(@NotNull ItemStack target) {
QModuleDrop> moduleDrop = ItemStats.getModule(target);
if (moduleDrop == null || !moduleDrop.isLoaded()) {
return false;
}
ModuleItem mItem = moduleDrop.getModuleItem(target);
return mItem != null && mItem instanceof RatedItem;
}
public void openGUIPaid(@NotNull Player player, @Nullable ItemStack target, boolean force) {
if (!force && !player.hasPermission(Perms.MAGIC_DUST_GUI)) {
plugin.lang().Error_NoPerm.send(player);
return;
}
if (target == null) {
target = new ItemStack(Material.AIR);
}
if (target.getType() != Material.AIR) {
if (!this.isRateableItem(target)) {
plugin.lang().MagicDust_GUI_Error_InvalidItem
.replace("%item%", ItemUT.getItemName(target))
.send(player);
return;
}
this.splitDragItem(player, null, target);
}
this.guiPaid.open(player, target);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onImproveRate(PlayerImproveItemSocketRateEvent e) {
Player player = e.getPlayer();
ItemStack target = e.getItem();
int rateFinal = e.getRateNew();
this.actionsApply.process(player);
plugin.lang().MagicDust_Apply_Done
.replace("%item%", ItemUT.getItemName(target))
.replace("%rate-new%", String.valueOf(rateFinal))
.send(player);
}
// -------------------------------------------------------------------- //
// CLASSES
public class MagicDust extends LimitedItem {
private final int rateMax;
private final TreeMap rateLvl;
public MagicDust(@NotNull Divinity plugin, @NotNull JYML cfg) {
super(plugin, cfg, MagicDustManager.this);
this.rateMax = Math.min(100, cfg.getInt("rate-increasing.max-value", 80));
this.rateLvl = new TreeMap<>();
for (String sLvl : cfg.getSection("rate-increasing.values-by-level")) {
int lvl = StringUT.getInteger(sLvl, -1);
if (lvl < 0) continue;
int rate = cfg.getInt("rate-increasing.values-by-level." + sLvl);
this.rateLvl.put(lvl, rate);
}
}
public int getMaxRate() {
return this.rateMax;
}
public int getRateByLevel(int lvl) {
Map.Entry e = this.rateLvl.floorEntry(lvl);
if (e == null) return 0;
return e.getValue();
}
@Override
@NotNull
protected ItemStack build(int lvl, int uses) {
ItemStack item = super.build(lvl, uses);
ItemMeta meta = item.getItemMeta();
if (meta == null) return item;
List lore = meta.getLore();
if (lore == null) return item;
int rate = this.getRateByLevel(lvl);
lore.replaceAll(str -> str
.replace("%rate-max%", String.valueOf(this.getMaxRate()))
.replace("%rate-amount%", String.valueOf(rate)));
meta.setLore(lore);
item.setItemMeta(meta);
return item;
}
}
class PaidGUI extends NGUI {
private final int itemSlot;
private final VaultHK vault;
private final boolean hasVault;
private final Set buttons;
public PaidGUI(@NotNull Divinity plugin) {
super(plugin, cfg, "gui.paid.");
this.buttons = new HashSet<>();
this.vault = plugin.getVault();
this.hasVault = this.vault != null && this.vault.getEconomy() != null;
String path = "gui.paid.";
this.itemSlot = cfg.getInt(path + "item-slot", 4);
for (String itemId : cfg.getSection(path + "dust-buttons")) {
GuiItem gi = cfg.getGuiItem(path + "dust-buttons." + itemId);
if (gi == null) continue;
String path2 = path + "dust-buttons." + itemId + ".";
int rateAmount = cfg.getInt(path2 + "rate-amount");
if (rateAmount == 0) continue;
double rateCost = this.hasVault ? cfg.getDouble(path2 + "rate-cost") : 0D;
int rateCap = cfg.getInt(path2 + "rate-max", 80);
ItemStack item = gi.getItem();
ItemMeta meta = item.getItemMeta();
if (meta == null) continue;
List lore = meta.getLore();
if (lore != null) {
lore.replaceAll(str -> str
.replace("%rate-max%", String.valueOf(rateCap)));
}
meta.setLore(lore);
item.setItemMeta(meta);
gi.setItem(item);
gi.setClick(new GuiClick() {
@Override
public void click(@NotNull Player p, @Nullable Enum> type, @NotNull InventoryClickEvent e) {
Inventory inv = e.getInventory();
ItemStack target = inv.getItem(itemSlot);
if (target == null || target.getType() == Material.AIR) return;
int rateHas = ItemStats.getSocketRate(target);
if (rateHas >= rateCap) {
plugin.lang().MagicDust_Apply_Error_MaxRate
.replace("%source%", getTitle())
.replace("%max-rate%", String.valueOf(rateHas))
.send(p);
MagicDustManager.this.actionsError.process(p);
return;
}
// Calc rate add amount depends on current item rate.
int rateDiff = (rateCap - rateHas);
int rateAmount2 = rateDiff >= rateAmount ? rateAmount : rateDiff;
// Do fair cost if not full rate amount will be added.
double rateCost2 = rateCost;
if (rateCost > 0 && rateAmount2 < rateAmount) {
double costDiff = (double) rateAmount2 / (double) rateAmount;
rateCost2 *= costDiff;
}
// Take user money for GUI dust operations.
if (rateCost2 > 0) {
double balance = vault.getBalance(p);
if (balance < rateCost2) {
plugin.lang().MagicDust_GUI_Error_TooExpensive
.replace("%cost%", NumberUT.format(rateCost2))
.replace("%balance%", NumberUT.format(balance))
.send(p);
MagicDustManager.this.actionsError.process(p);
return;
}
}
// Call custom plugin event.
PlayerImproveItemSocketRateEvent event =
new PlayerImproveItemSocketRateEvent(p, target, rateHas, rateHas + rateAmount2);
plugin.getPluginManager().callEvent(event);
if (event.isCancelled()) {
MagicDustManager.this.actionsError.process(p);
return;
}
// Take money only at the end of operation.
PaidGUI.this.vault.take(p, rateCost2);
// A bit hacky way to prevent duplication due to
// onClose event item return and JGUI re-open while it's opened.
inv.setItem(itemSlot, null);
ItemUT.addItem(p, target = changeItemRate(target, rateAmount2));
openGUIPaid(p, target, true);
}
});
this.buttons.add(gi);
}
GuiClick click = new GuiClick() {
@Override
public void click(@NotNull Player p, @Nullable Enum> type, @NotNull InventoryClickEvent e) {
if (type == ContentType.EXIT) {
p.closeInventory();
}
}
};
for (String itemId : cfg.getSection(path + "content")) {
GuiItem guiItem = cfg.getGuiItem(path + "content." + itemId, ContentType.class);
if (guiItem == null) continue;
if (guiItem.getType() != null) {
guiItem.setClick(click);
}
this.addButton(guiItem);
}
}
public void open(@NotNull Player player, @NotNull ItemStack target) {
// Fix GUI issues when re-open it.
// NOT A BUG, but not intended JGUI usage.
this.clearUserCache(player);
this.LOCKED_CACHE.add(player.getName());
this.addButton(player, new JIcon(target), this.itemSlot);
int rateHas = ItemStats.getSocketRate(target);
double balance = this.hasVault ? this.vault.getBalance(player) : 0D;
// Hack to replace GUI item placeholders.
for (GuiItem gi : this.buttons) {
ItemStack item = gi.getItem();
ItemMeta meta = item.getItemMeta();
if (meta == null) continue;
List lore = meta.getLore();
if (lore != null) {
// Accessing button values via module config is the only way.
int rateAmount = cfg.getInt("gui.paid.dust-buttons." + gi.getId() + ".rate-amount");
int rateCap = cfg.getInt("gui.paid.dust-buttons." + gi.getId() + ".rate-max");
double rateCost =
this.hasVault ? cfg.getInt("gui.paid.dust-buttons." + gi.getId() + ".rate-cost") : 0D;
int rateDiff = (rateCap - rateHas);
int rateAmount2 = rateDiff >= rateAmount ? rateAmount : rateDiff;
// Do fair cost if not full rate amount will be added.
if (rateCost > 0 && rateAmount2 < rateAmount) {
double costDiff = (double) rateAmount2 / (double) rateAmount;
rateCost *= costDiff;
}
double rateCost2 = rateCost;
lore.replaceAll(str -> str
.replace("%cost%", NumberUT.format(rateCost2))
.replace("%balance%", NumberUT.format(balance))
.replace("%rate-new%", String.valueOf(rateHas + rateAmount2))
.replace("%rate-old%", String.valueOf(rateHas)));
meta.setLore(lore);
item.setItemMeta(meta);
}
JIcon icon = new JIcon(item);
icon.setClick(gi.getClick());
for (int slot : gi.getSlots()) {
this.addButton(player, icon, slot);
}
}
super.open(player, 1);
}
@Override
protected boolean cancelClick(int slot) {
return true;
}
@Override
protected boolean cancelPlayerClick() {
return true;
}
@Override
protected boolean ignoreNullClick() {
return true;
}
@Override
protected void onCreate(@NotNull Player player, @NotNull Inventory inv, int page) {
}
@Override
protected void click(@NotNull Player player,
@Nullable ItemStack item,
int slot,
@NotNull InventoryClickEvent e) {
Inventory inv = e.getInventory();
ItemStack target = inv.getItem(itemSlot);
// Return GUI item to player inventory.
if (slot == this.itemSlot && target != null && target.getType() != Material.AIR) {
inv.setItem(itemSlot, target);
open(player, new ItemStack(Material.AIR));
return;
}
// Place user item to the GUI.
if (slot > this.getSize() && (target == null || target.getType() == Material.AIR)) {
if (item == null || item.getType() == Material.AIR) return;
openGUIPaid(player, item, true);
return;
}
super.click(player, item, slot, e);
}
@Override
protected void onClose(@NotNull Player player, @NotNull InventoryCloseEvent e) {
Inventory inv = e.getInventory();
ItemStack target = inv.getItem(itemSlot);
// Return user items on GUI close to avoid item losing.
if (target != null && target.getType() != Material.AIR) {
ItemUT.addItem(player, target);
}
super.onClose(player, e);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy