diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..73eeaa5 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,11 @@ +jdk: + - openjdk16 + +before_install: + - sdk install java 16.0.1-open + - sdk use java 16.0.1-open + - sdk install maven + - mvn -v + +install: + - mvn install -DskipTests diff --git a/pom.xml b/pom.xml index 120ef52..ef01ef9 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ Shops Shops is the ultimate solution for server shops - 4.0.0 + 4.11.0 jar @@ -16,7 +16,7 @@ ${project.name} ${project.groupId}.${project.artifactId}.${project.name} 16 - 3.18.0 + 3.30.0 ca.tweetzy UTF-8 @@ -47,6 +47,10 @@ opencollab-snapshot https://repo.opencollab.dev/maven-snapshots/ + + auxilor-plugins + https://repo.auxilor.io/repository/maven-public/ + @@ -59,7 +63,7 @@ org.spigotmc spigot - 1.20.4-R0.1-SNAPSHOT + 1.21.4-R0.1-SNAPSHOT provided @@ -70,7 +74,7 @@ ${flight.path} funds - 1.7.0 + 1.10.0 * @@ -78,6 +82,12 @@ + + com.willfp + EcoBits + 1.8.4 + provided + com.github.MilkBowl VaultAPI @@ -195,50 +205,68 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + maven-resources-plugin + 3.0.2 + + + copy-files-on-build + package + + copy-resources + + + D:\Development\Spigot Servers\Latest Version\plugins + + + ${project.build.directory} + ${project.name}.jar + false + + + + + + + + com.coderplus.maven.plugins + copy-rename-maven-plugin + 1.0.1 + + + copy-named-jar + package + + copy + + + ${project.build.directory}/${project.name}.jar + D:\Development\Spigot Plugins\Ready Jars\${project.name}\${project.name} - v${project.version}.jar + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + test + + run + + + + + + + + + + + + diff --git a/src/main/java/ca/tweetzy/shops/Shops.java b/src/main/java/ca/tweetzy/shops/Shops.java index fff9dfa..d4e5f64 100644 --- a/src/main/java/ca/tweetzy/shops/Shops.java +++ b/src/main/java/ca/tweetzy/shops/Shops.java @@ -80,6 +80,7 @@ protected void onFlight() { new DeleteCommand(), new CartCommand(), new AdminCommand(), + new PrefillCommand(), new ReloadCommand() ); } diff --git a/src/main/java/ca/tweetzy/shops/api/cart/CartContent.java b/src/main/java/ca/tweetzy/shops/api/cart/CartContent.java index 9e140a3..89715d4 100644 --- a/src/main/java/ca/tweetzy/shops/api/cart/CartContent.java +++ b/src/main/java/ca/tweetzy/shops/api/cart/CartContent.java @@ -59,6 +59,7 @@ default TransactionResult executeSell(@NonNull final Player player) { if (totalFoundInInventory == 0) return TransactionResult.PLAYER_DOES_NOT_HAVE_ITEM; + final int amountToSell = Math.min(getQuantity(), totalFoundInInventory); final double subTotal = getSellSubtotal(amountToSell); diff --git a/src/main/java/ca/tweetzy/shops/api/shop/ShopDisplay.java b/src/main/java/ca/tweetzy/shops/api/shop/ShopDisplay.java index 48df606..bee0976 100644 --- a/src/main/java/ca/tweetzy/shops/api/shop/ShopDisplay.java +++ b/src/main/java/ca/tweetzy/shops/api/shop/ShopDisplay.java @@ -37,6 +37,10 @@ public interface ShopDisplay extends Jsonable { void setCartButtonSlot(final int slot); + int getSellButtonSlot(); + + void setSellButtonSlot(final int slot); + List getFillSlots(); void setFillSlots(final List slots); diff --git a/src/main/java/ca/tweetzy/shops/api/shop/ShopLayoutControl.java b/src/main/java/ca/tweetzy/shops/api/shop/ShopLayoutControl.java index e31c8ea..70feff9 100644 --- a/src/main/java/ca/tweetzy/shops/api/shop/ShopLayoutControl.java +++ b/src/main/java/ca/tweetzy/shops/api/shop/ShopLayoutControl.java @@ -7,5 +7,6 @@ public enum ShopLayoutControl { NEXT_PAGE_BUTTON, SEARCH_BUTTON, FILTER_BUTTON, - CART_BUTTON + CART_BUTTON, + SELL_BUTTON } diff --git a/src/main/java/ca/tweetzy/shops/commands/PrefillCommand.java b/src/main/java/ca/tweetzy/shops/commands/PrefillCommand.java new file mode 100644 index 0000000..3861b48 --- /dev/null +++ b/src/main/java/ca/tweetzy/shops/commands/PrefillCommand.java @@ -0,0 +1,223 @@ +package ca.tweetzy.shops.commands; + +import ca.tweetzy.flight.command.AllowedExecutor; +import ca.tweetzy.flight.command.Command; +import ca.tweetzy.flight.command.ReturnType; +import ca.tweetzy.flight.comp.enums.CompMaterial; +import ca.tweetzy.flight.gui.helper.InventorySafeMaterials; +import ca.tweetzy.flight.utils.QuickItem; +import ca.tweetzy.shops.Shops; +import ca.tweetzy.shops.api.shop.Shop; +import ca.tweetzy.shops.impl.shop.ItemShopContent; +import ca.tweetzy.shops.impl.shop.ServerShop; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.UUID; + +public final class PrefillCommand extends Command { + + public PrefillCommand() { + super(AllowedExecutor.BOTH, "prefill"); + } + + @Override + protected ReturnType execute(CommandSender sender, String... args) { + if (args.length < 1) { + tellNoPrefix(sender, "&4Please use &c/shops prefill confirm &4to execute"); + tellNoPrefix(sender, "&eBy doing this you acknowledge that any existing shop will either be deleted/cleared and re-populated with template items. The items that go into the shop &4MAY NOT BE &ecorrectly categorized. All prices and minimum quantities are also set to the same values regardless of what it is."); + return ReturnType.FAIL; + } + + + final boolean confirmed = args[0].equalsIgnoreCase("confirm"); + + if (!confirmed) return ReturnType.FAIL; + + if (!Shops.getShopManager().getValues().isEmpty()) { + // yeet shops + for (Shop shop : Shops.getShopManager().getValues()) { + shop.unStore(result -> { + }); + } + } + + // create base shops + + // FOOD + Shop foodShop = new ServerShop("food"); + foodShop.getShopOptions().setDisplayIcon(new ItemStack(Material.CAKE, 1)); + + Shops.getShopManager().create(foodShop, created -> { + if (created) { + for (Material material : Material.values()) { + if (material == null || material == Material.AIR || !material.isEdible()) continue; + foodShop.addContent(new ItemShopContent(UUID.randomUUID(), foodShop.getId(), new ItemStack(material, 1), 1, 1, 0.5)); + } + } + }); + + // BLOCKS + Shop blockShop = new ServerShop("blocks"); + blockShop.getShopOptions().setDisplayIcon(new ItemStack(Material.GRASS_BLOCK, 1)); + + Shops.getShopManager().create(blockShop, created -> { + if (created) { + for (CompMaterial safe : InventorySafeMaterials.get()) { + if (safe.parseMaterial().isEdible() || !safe.parseMaterial().isBlock()) continue; + blockShop.addContent(new ItemShopContent(UUID.randomUUID(), blockShop.getId(), safe.parseItem(), 1, 1, 0.5)); + } + } + }); + + // ARMOR + Shop armorShop = new ServerShop("armor"); + armorShop.getShopOptions().setDisplayIcon(new ItemStack(Material.DIAMOND_HELMET, 1)); + + Shops.getShopManager().create(armorShop, created -> { + if (created) { + for (Material material : Material.values()) { + if (material == null || material == Material.AIR || material.isEdible() || !isArmor(material)) continue; + armorShop.addContent(new ItemShopContent(UUID.randomUUID(), armorShop.getId(), new ItemStack(material, 1), 1, 1, 0.5)); + } + } + }); + + Shop weaponsShop = new ServerShop("weapons"); + weaponsShop.getShopOptions().setDisplayIcon(new ItemStack(Material.IRON_SWORD, 1)); + + Shops.getShopManager().create(weaponsShop, created -> { + if (created) { + for (Material material : Material.values()) { + if (material == null || material == Material.AIR || !isWeapon(material)) continue; + weaponsShop.addContent(new ItemShopContent(UUID.randomUUID(), weaponsShop.getId(), new ItemStack(material, 1), 1, 1, 0.5)); + } + } + }); + + Shop toolShop = new ServerShop("tools"); + toolShop.getShopOptions().setDisplayIcon(new ItemStack(Material.NETHERITE_PICKAXE, 1)); + + Shops.getShopManager().create(toolShop, created -> { + if (created) { + for (Material material : Material.values()) { + + if (material == null || material == Material.AIR || !isTool(material)) continue; + toolShop.addContent(new ItemShopContent(UUID.randomUUID(), toolShop.getId(), new ItemStack(material, 1), 1, 1, 0.5)); + } + } + }); + + Shop potionsShop = new ServerShop("potions"); + potionsShop.getShopOptions().setDisplayIcon(new ItemStack(Material.LINGERING_POTION, 1)); + + Shops.getShopManager().create(potionsShop, created -> { + if (created) { + potionsShop.addContent(new ItemShopContent(UUID.randomUUID(), toolShop.getId(), QuickItem.of(CompMaterial.POTION).name("&ePotions Are Weird").lore("&7Since there are a bunch of variants, you will", "&7have to add them in manually.").make(), 1, 1, 0.5)); + } + }); + + Shop raidingShop = new ServerShop("raiding"); + raidingShop.getShopOptions().setDisplayIcon(new ItemStack(Material.TNT, 1)); + + Shops.getShopManager().create(raidingShop, created -> { + if (created) { + raidingShop.addContent(new ItemShopContent(UUID.randomUUID(), raidingShop.getId(), new ItemStack(Material.TNT, 1), 1, 1, 0.5)); + raidingShop.addContent(new ItemShopContent(UUID.randomUUID(), raidingShop.getId(), new ItemStack(Material.TNT_MINECART, 1), 1, 1, 0.5)); + } + }); + + Shop redstoneShop = new ServerShop("redstone"); + redstoneShop.getShopOptions().setDisplayIcon(new ItemStack(Material.REDSTONE, 1)); + + Shops.getShopManager().create(redstoneShop, created -> { + if (created) { + for (Material material : Material.values()) { + if (material == null || material == Material.AIR || !isRedstone(material)) continue; + redstoneShop.addContent(new ItemShopContent(UUID.randomUUID(), redstoneShop.getId(), new ItemStack(material, 1), 1, 1, 0.5)); + } + } + }); + + return ReturnType.SUCCESS; + } + + @Override + protected List tab(CommandSender sender, String... args) { + return null; + } + + @Override + public String getPermissionNode() { + return "shops.command.prefill"; + } + + @Override + public String getSyntax() { + return "prefill "; + } + + @Override + public String getDescription() { + return "Used quickly create template categories and populate"; + } + + private boolean isArmor(final Material material) { + final String typeNameString = material.name(); + return typeNameString.endsWith("_HELMET") + || typeNameString.endsWith("_CHESTPLATE") + || typeNameString.endsWith("_LEGGINGS") + || typeNameString.endsWith("_BOOTS"); + } + + private boolean isWeapon(final Material material) { + final String typeNameString = material.name(); + return typeNameString.endsWith("_SWORD") + || typeNameString.endsWith("_AXE") + || material == Material.BOW + || material == Material.CROSSBOW + || material == Material.TRIDENT + || material == Material.ARROW + || material == Material.SHIELD; + } + + private boolean isTool(final Material material) { + final String typeNameString = material.name(); + return typeNameString.endsWith("_HOE") + || typeNameString.endsWith("_SHOVEL") + || typeNameString.endsWith("_PICKAXE") + || material == Material.FISHING_ROD + || material == Material.COMPASS + || material == Material.CLOCK + || material == Material.LEAD + || material == Material.SHEARS + || typeNameString.contains("BUCKET"); + } + + private boolean isRedstone(final Material material) { + final String typeNameString = material.name(); + return material == Material.REDSTONE + || typeNameString.endsWith("_PLATE") + || typeNameString.endsWith("_BUTTON") + || material == Material.REDSTONE_BLOCK + || material == Material.REDSTONE_LAMP + || material == Material.REDSTONE_TORCH + || material == Material.REPEATER + || material == Material.COMPARATOR + || material == Material.LEVER + || material == Material.HOPPER + || material == Material.OBSERVER + || material == Material.STICKY_PISTON + || material == Material.PISTON + || material == Material.SLIME_BLOCK + || material == Material.HONEY_BLOCK + || material == Material.ACTIVATOR_RAIL + || material == Material.POWERED_RAIL + || material == Material.DETECTOR_RAIL + || material == Material.DROPPER + || material == Material.DISPENSER + || material == Material.SHIELD; + } +} diff --git a/src/main/java/ca/tweetzy/shops/gui/ShopsBaseGUI.java b/src/main/java/ca/tweetzy/shops/gui/ShopsBaseGUI.java index b9ffa8e..46d9cad 100644 --- a/src/main/java/ca/tweetzy/shops/gui/ShopsBaseGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/ShopsBaseGUI.java @@ -3,6 +3,7 @@ import ca.tweetzy.flight.gui.Gui; import ca.tweetzy.flight.gui.template.BaseGUI; import ca.tweetzy.flight.settings.TranslationManager; +import ca.tweetzy.flight.utils.Common; import ca.tweetzy.flight.utils.QuickItem; import ca.tweetzy.shops.settings.Settings; import ca.tweetzy.shops.settings.Translations; @@ -19,16 +20,22 @@ public abstract class ShopsBaseGUI extends BaseGUI { public ShopsBaseGUI(Gui parent, @NonNull final Player player, @NonNull String title, int rows) { super(parent, title, rows); this.player = player; + + + setGlobalClickDelay(Settings.GLOBAL_GUI_CLICK_DELAY.getInt()); + + if (Settings.SEND_CLICK_DELAY_MSG.getBoolean()) + setClickDelayAction(click -> Common.tell(click.player, TranslationManager.string(Translations.CLICKING_TOO_FAST))); } public ShopsBaseGUI(Gui parent, @NonNull final Player player, @NonNull String title) { super(parent, title); this.player = player; - } - public ShopsBaseGUI(@NonNull final Player player, @NonNull String title) { - super(title); - this.player = player; + setGlobalClickDelay(Settings.GLOBAL_GUI_CLICK_DELAY.getInt()); + + if (Settings.SEND_CLICK_DELAY_MSG.getBoolean()) + setClickDelayAction(click -> Common.tell(click.player, TranslationManager.string(Translations.CLICKING_TOO_FAST))); } @Override diff --git a/src/main/java/ca/tweetzy/shops/gui/ShopsPagedGUI.java b/src/main/java/ca/tweetzy/shops/gui/ShopsPagedGUI.java index 018c361..d192bab 100644 --- a/src/main/java/ca/tweetzy/shops/gui/ShopsPagedGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/ShopsPagedGUI.java @@ -4,6 +4,7 @@ import ca.tweetzy.flight.gui.events.GuiClickEvent; import ca.tweetzy.flight.gui.template.BaseGUI; import ca.tweetzy.flight.settings.TranslationManager; +import ca.tweetzy.flight.utils.Common; import ca.tweetzy.flight.utils.QuickItem; import ca.tweetzy.shops.settings.Settings; import ca.tweetzy.shops.settings.Translations; @@ -27,10 +28,11 @@ public ShopsPagedGUI(Gui parent, @NonNull final Player player, @NonNull String t this.parent = parent; this.player = player; this.items = items; - } - public ShopsPagedGUI(@NonNull final Player player, @NonNull String title, int rows, @NonNull List items) { - this(null, player, title, rows, items); + setGlobalClickDelay(Settings.GLOBAL_GUI_CLICK_DELAY.getInt()); + + if (Settings.SEND_CLICK_DELAY_MSG.getBoolean()) + setClickDelayAction(click -> Common.tell(click.player, TranslationManager.string(Translations.CLICKING_TOO_FAST))); } @Override diff --git a/src/main/java/ca/tweetzy/shops/gui/admin/ShopEditGUI.java b/src/main/java/ca/tweetzy/shops/gui/admin/ShopEditGUI.java index b26281f..74903f7 100644 --- a/src/main/java/ca/tweetzy/shops/gui/admin/ShopEditGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/admin/ShopEditGUI.java @@ -65,7 +65,7 @@ protected void drawFixed() { // quick selector if (click.clickType == ClickType.RIGHT) click.manager.showGUI(click.player, new MaterialPickerGUI(this, null, "", (event, selected) -> { - click.manager.showGUI(click.player, new ShopAddContentItemGUI(click.player, this.shop, ItemShopContent.blank(this.shop.getId(), selected), false)); + click.manager.showGUI(click.player, new ShopAddContentItemGUI(click.player, this.shop, ItemShopContent.blank(this.shop.getId(), CompMaterial.matchCompMaterial(selected)), false)); })); }); diff --git a/src/main/java/ca/tweetzy/shops/gui/admin/ShopSettingsGUI.java b/src/main/java/ca/tweetzy/shops/gui/admin/ShopSettingsGUI.java index febb4bf..d8a3289 100644 --- a/src/main/java/ca/tweetzy/shops/gui/admin/ShopSettingsGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/admin/ShopSettingsGUI.java @@ -4,6 +4,7 @@ import ca.tweetzy.flight.comp.enums.CompMaterial; import ca.tweetzy.flight.gui.template.MaterialPickerGUI; import ca.tweetzy.flight.settings.TranslationManager; +import ca.tweetzy.flight.utils.Common; import ca.tweetzy.flight.utils.QuickItem; import ca.tweetzy.flight.utils.input.TitleInput; import ca.tweetzy.shops.Shops; @@ -12,6 +13,7 @@ import ca.tweetzy.shops.commands.DynamicShopCommand; import ca.tweetzy.shops.gui.ShopsBaseGUI; import ca.tweetzy.shops.gui.admin.layout.ShopLayoutEditorGUI; +import ca.tweetzy.shops.impl.currency.ItemCurrency; import ca.tweetzy.shops.settings.Translations; import lombok.NonNull; import org.bukkit.ChatColor; @@ -29,6 +31,7 @@ public final class ShopSettingsGUI extends ShopsBaseGUI { public ShopSettingsGUI(@NonNull Player player, @NonNull final Shop shop) { super(new ShopEditGUI(player, shop), player, TranslationManager.string(Translations.GUI_SHOP_SETTINGS_TITLE, "shop_id", shop.getId()), 6); this.shop = shop; + setAcceptsItems(true); draw(); } @@ -48,7 +51,7 @@ protected void draw() { if (material == null) return; final ItemStack oldIcon = this.shop.getShopOptions().getDisplayIcon(); - final ItemStack newIcon = material.parseItem(); + final ItemStack newIcon = material; assert newIcon != null; this.shop.getShopOptions().setDisplayIcon(newIcon); @@ -129,8 +132,33 @@ public boolean onResult(String string) { setButton(3, 4, QuickItem .of(CompMaterial.CARTOGRAPHY_TABLE) .name(TranslationManager.string(Translations.GUI_SHOP_SETTINGS_ITEMS_DECO_NAME)) - .lore(TranslationManager.list(Translations.GUI_SHOP_SETTINGS_ITEMS_DECO_LORE)) - .make(), click -> click.manager.showGUI(click.player, new ShopLayoutEditorGUI(click.player, this.shop))); + .lore(TranslationManager.list(Translations.GUI_SHOP_SETTINGS_ITEMS_DECO_LORE, + "left_click", TranslationManager.string(this.player, Translations.MOUSE_LEFT_CLICK), + "right_click", TranslationManager.string(this.player, Translations.MOUSE_RIGHT_CLICK))) + .make(), click -> { + + if (click.clickType == ClickType.LEFT) { + click.manager.showGUI(click.player, new ShopLayoutEditorGUI(click.player, this.shop)); + return; + } + + if (click.clickType == ClickType.RIGHT) { + final ItemStack cursor = click.cursor; + if (cursor != null && cursor.getType() != CompMaterial.AIR.parseMaterial()) { + final ItemStack newBG = cursor.clone(); + newBG.setAmount(1); + this.shop.getShopOptions().getShopDisplay().setBackgroundItem(newBG); + } else { + this.shop.getShopOptions().getShopDisplay().setBackgroundItem(QuickItem.of(CompMaterial.AIR).make()); + } + + this.shop.sync(result -> { + if (result == SynchronizeResult.SUCCESS) + Common.tell(click.player, TranslationManager.string(click.player, Translations.UPDATED_SHOP_BG)); + }); + + } + }); // permission setButton(3, 2, QuickItem diff --git a/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentCmdGUI.java b/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentCmdGUI.java index 7d9c9c6..8a5adb9 100644 --- a/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentCmdGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentCmdGUI.java @@ -104,7 +104,7 @@ private void drawIcon() { if (click.clickType == ClickType.LEFT) { click.manager.showGUI(click.player, new MaterialPickerGUI(this, null, "", (event, selected) -> { - this.commandShopContent.setIcon(selected.parseItem()); + this.commandShopContent.setIcon(selected); click.manager.showGUI(click.player, new ShopAddContentCmdGUI(click.player, ShopAddContentCmdGUI.this.shop, ShopAddContentCmdGUI.this.commandShopContent, ShopAddContentCmdGUI.this.isEditing)); })); } diff --git a/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentItemGUI.java b/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentItemGUI.java index f3d70c7..0128e84 100644 --- a/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentItemGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/admin/content/ShopAddContentItemGUI.java @@ -101,7 +101,7 @@ private void drawSellItem() { if (click.clickType == ClickType.LEFT) { click.manager.showGUI(click.player, new MaterialPickerGUI(this, null, "", (event, selected) -> { - this.itemContent.setItem(selected.parseItem()); + this.itemContent.setItem(selected); click.manager.showGUI(click.player, new ShopAddContentItemGUI(click.player, ShopAddContentItemGUI.this.shop, ShopAddContentItemGUI.this.itemContent, ShopAddContentItemGUI.this.isEditing)); })); } diff --git a/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutControlPickerGUI.java b/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutControlPickerGUI.java index 924bd93..f1eb14f 100644 --- a/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutControlPickerGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutControlPickerGUI.java @@ -71,6 +71,11 @@ protected ItemStack makeDisplayItem(ShopLayoutControl layoutControl) { .name(TranslationManager.string(this.player, Translations.GUI_LAYOUT_CONTROL_PICKER_ITEMS_CART_NAME)) .lore(TranslationManager.list(this.player, Translations.GUI_LAYOUT_CONTROL_PICKER_ITEMS_CART_LORE, "left_click", TranslationManager.string(this.player, Translations.MOUSE_LEFT_CLICK))) .make(); + case SELL_BUTTON -> QuickItem + .of(Settings.GUI_LAYOUT_CONTROL_PICKER_ITEMS_SELL.getItemStack()) + .name(TranslationManager.string(this.player, Translations.GUI_LAYOUT_CONTROL_PICKER_ITEMS_SELL_NAME)) + .lore(TranslationManager.list(this.player, Translations.GUI_LAYOUT_CONTROL_PICKER_ITEMS_SELL_LORE, "left_click", TranslationManager.string(this.player, Translations.MOUSE_LEFT_CLICK))) + .make(); }; } diff --git a/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutEditorGUI.java b/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutEditorGUI.java index d2ef6a6..6632894 100644 --- a/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutEditorGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/admin/layout/ShopLayoutEditorGUI.java @@ -66,6 +66,12 @@ protected void drawFixed() { .lore(TranslationManager.list(this.player, Translations.GUI_LAYOUT_EDITOR_ITEMS_CART_LORE)) .make()); + setItem(layout.getSellButtonSlot(), QuickItem + .of(CompMaterial.ENDER_CHEST) + .name(TranslationManager.string(this.player, Translations.GUI_LAYOUT_EDITOR_ITEMS_SELL_NAME)) + .lore(TranslationManager.list(this.player, Translations.GUI_LAYOUT_EDITOR_ITEMS_SELL_LORE)) + .make()); + } @Override @@ -136,6 +142,7 @@ else if (isEmptySlot(slot)) { case SEARCH_BUTTON -> layout.setSearchButtonSlot(slot); case FILTER_BUTTON -> layout.setFilterButtonSlot(slot); case CART_BUTTON -> layout.setCartButtonSlot(slot); + case SELL_BUTTON -> layout.setSellButtonSlot(slot); } layout.getFillSlots().remove(slot); @@ -178,7 +185,8 @@ private boolean isEmptySlot(final int slot) { && layout.getPrevPageButtonSlot() != slot && layout.getSearchButtonSlot() != slot && layout.getFilterButtonSlot() != slot - && layout.getCartButtonSlot() != slot; + && layout.getCartButtonSlot() != slot + && layout.getSellButtonSlot() != slot; } private ItemStack emptySlotItem() { diff --git a/src/main/java/ca/tweetzy/shops/gui/selector/CurrencyPickerGUI.java b/src/main/java/ca/tweetzy/shops/gui/selector/CurrencyPickerGUI.java index b8faf19..9373785 100644 --- a/src/main/java/ca/tweetzy/shops/gui/selector/CurrencyPickerGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/selector/CurrencyPickerGUI.java @@ -53,7 +53,7 @@ protected void drawFixed() { if (click.clickType == ClickType.RIGHT) { click.manager.showGUI(click.player, new MaterialPickerGUI(this, null, null, (event, selected) -> { if (selected != null) { - this.selectedCurrency.accept(new ItemCurrency(), selected.parseItem()); + this.selectedCurrency.accept(new ItemCurrency(), selected); } })); } diff --git a/src/main/java/ca/tweetzy/shops/gui/user/ShopCheckoutGUI.java b/src/main/java/ca/tweetzy/shops/gui/user/ShopCheckoutGUI.java index e9b69c9..13e175f 100644 --- a/src/main/java/ca/tweetzy/shops/gui/user/ShopCheckoutGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/user/ShopCheckoutGUI.java @@ -1,7 +1,9 @@ package ca.tweetzy.shops.gui.user; +import ca.tweetzy.flight.comp.enums.CompMaterial; import ca.tweetzy.flight.gui.Gui; import ca.tweetzy.flight.settings.TranslationManager; +import ca.tweetzy.flight.utils.Common; import ca.tweetzy.flight.utils.QuickItem; import ca.tweetzy.shops.Shops; import ca.tweetzy.shops.api.cart.CartContent; @@ -26,14 +28,21 @@ public final class ShopCheckoutGUI extends ShopsBaseGUI { private final Shop shop; private final CartContent checkoutItem; + private boolean isSelling = false; + private boolean fromSpawners; - public ShopCheckoutGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop, @NonNull CartContent checkoutItem) { + public ShopCheckoutGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop, @NonNull CartContent checkoutItem, boolean fromSpawners) { super(parent, player, TranslationManager.string(player, Translations.GUI_CHECKOUT_TITLE)); this.shop = shop; this.checkoutItem = checkoutItem; + this.fromSpawners = fromSpawners; draw(); } + public ShopCheckoutGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop, @NonNull CartContent checkoutItem) { + this(parent, player, shop, checkoutItem, false); + } + @Override protected void draw() { drawSelectedItem(); @@ -73,16 +82,31 @@ protected void draw() { }); }); + drawBuySellButton(); + + if (this.checkoutItem.getItem().isAllowSell() && !this.fromSpawners) + drawSellToggleButton(); + + drawPriceBreakdown(); + + applyBackExit(); + } + + private void drawSelectedItem() { + setItem(1, 4, this.checkoutItem.getItem().generateDisplayItem(ShopContentDisplayType.CHECKOUT, this.checkoutItem.getQuantity())); + } + + private void drawBuySellButton() { setButton(getRows() - 1, 4, QuickItem .of(Settings.GUI_CHECKOUT_ITEMS_CHECKOUT.getItemStack()) - .name(TranslationManager.string(this.player, Translations.GUI_CHECKOUT_ITEMS_PURCHASE_NAME)) - .lore(TranslationManager.list(this.player, Translations.GUI_CHECKOUT_ITEMS_PURCHASE_LORE, + .name(TranslationManager.string(this.player, this.isSelling ? Translations.GUI_CHECKOUT_ITEMS_SELL_NAME : Translations.GUI_CHECKOUT_ITEMS_PURCHASE_NAME)) + .lore(TranslationManager.list(this.player, this.isSelling ? Translations.GUI_CHECKOUT_ITEMS_SELL_LORE : Translations.GUI_CHECKOUT_ITEMS_PURCHASE_LORE, "left_click", TranslationManager.string(this.player, Translations.MOUSE_LEFT_CLICK), "right_click", TranslationManager.string(this.player, Translations.MOUSE_RIGHT_CLICK) )).make(), click -> { if (click.clickType == ClickType.LEFT) { - final TransactionResult transactionResult = this.checkoutItem.executePurchase(player); + final TransactionResult transactionResult = this.isSelling ? this.checkoutItem.executeSell(player) : this.checkoutItem.executePurchase(player); click.manager.showGUI(click.player, new ShopContentsGUI(new ShopsMainGUI(null, click.player), click.player, this.shop)); } @@ -92,26 +116,39 @@ protected void draw() { } }); - - drawPriceBreakdown(); - applyBackExit(); } - private void drawSelectedItem() { - setItem(1, 4, this.checkoutItem.getItem().generateDisplayItem(ShopContentDisplayType.CHECKOUT, this.checkoutItem.getQuantity())); + private void drawSellToggleButton() { + setButton(getRows() - 1, 8, QuickItem + .of(this.isSelling ? CompMaterial.REDSTONE_TORCH : CompMaterial.TORCH) + .name(TranslationManager.string(Translations.GUI_CHECKOUT_ITEMS_TOGGLE_SELL_NAME)) + .lore(TranslationManager.list(Translations.GUI_CHECKOUT_ITEMS_TOGGLE_SELL_LORE, "is_true", TranslationManager.string(!this.isSelling ? Translations.ENABLED : Translations.DISABLED))) + .make(), click -> { + + if (!this.checkoutItem.getItem().isAllowSell()) { + Common.tell(click.player, TranslationManager.string(Translations.SELL_NOT_ALLOWED)); + return; + } + + this.isSelling = !this.isSelling; + drawSellToggleButton(); + drawPriceBreakdown(); + drawBuySellButton(); + }); } private void drawPriceBreakdown() { - final double subtotal = this.checkoutItem.getBuySubtotal(this.checkoutItem.getQuantity()); - final double total = Taxer.getTaxedTotal(subtotal); + final double subtotal = this.isSelling ? this.checkoutItem.getSellSubtotal(this.checkoutItem.getQuantity()) : this.checkoutItem.getBuySubtotal(this.checkoutItem.getQuantity()); + final double total = this.isSelling ? subtotal : Taxer.getTaxedTotal(subtotal); final String numberFormatSub = this.checkoutItem.getItem().isCurrencyOfItem() ? (int) subtotal + " " + this.checkoutItem.getItem().getCurrencyDisplayName() : NumberHelper.format(subtotal); final String numberFormatTotal = this.checkoutItem.getItem().isCurrencyOfItem() ? (int) total + " " + this.checkoutItem.getItem().getCurrencyDisplayName() : NumberHelper.format(total); - List base = TranslationManager.list(this.player, Translations.GUI_CHECKOUT_ITEMS_BREAKDOWN_LORE, + List base = TranslationManager.list(this.player, this.isSelling ? Translations.GUI_CHECKOUT_ITEMS_BREAKDOWN_SELL_LORE : Translations.GUI_CHECKOUT_ITEMS_BREAKDOWN_LORE, "checkout_item_qty", this.checkoutItem.getQuantity(), "checkout_item_buy_subtotal", numberFormatSub, - "checkout_item_buy_total", numberFormatTotal + "checkout_item_buy_total", numberFormatTotal, + "checkout_item_sell_total", numberFormatTotal ); VariableHelper.replaceVariable(base, "%checkout_tax_info%", Settings.TAX_ENABLED.getBoolean() ? diff --git a/src/main/java/ca/tweetzy/shops/gui/user/ShopContentsGUI.java b/src/main/java/ca/tweetzy/shops/gui/user/ShopContentsGUI.java index 30ea384..e50b225 100644 --- a/src/main/java/ca/tweetzy/shops/gui/user/ShopContentsGUI.java +++ b/src/main/java/ca/tweetzy/shops/gui/user/ShopContentsGUI.java @@ -1,5 +1,6 @@ package ca.tweetzy.shops.gui.user; +import ca.tweetzy.flight.comp.enums.CompMaterial; import ca.tweetzy.flight.gui.Gui; import ca.tweetzy.flight.gui.events.GuiClickEvent; import ca.tweetzy.flight.settings.TranslationManager; @@ -34,18 +35,30 @@ public final class ShopContentsGUI extends ShopsPagedGUI { private FilterOrder filterOrder; private FilterType filterType; - public ShopContentsGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop, final String search) { + private boolean fromSpawners; + + public ShopContentsGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop, final String search, final boolean fromSpawners) { super(parent, player, shop.getDisplayName(), Math.max(2, shop.getShopOptions().getShopDisplay().getRows()), shop.getContent()); this.shop = shop; this.cart = Shops.getCartManager().getOrAdd(player); this.filterType = FilterType.NAME; this.filterOrder = FilterOrder.ASCENDING; this.search = search; + this.fromSpawners = fromSpawners; + // apply default item + final ItemStack bg = this.shop.getShopOptions().getShopDisplay().getBackgroundItem(); + + setDefaultItem(bg.getType() == CompMaterial.AIR.parseMaterial() ? null : QuickItem.bg(bg)); + draw(); } public ShopContentsGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop) { - this(parent, player, shop, null); + this(parent, player, shop, null, false); + } + + public ShopContentsGUI(Gui parent, @NonNull Player player, @NonNull final Shop shop, final boolean fromSpawners) { + this(parent, player, shop, null, fromSpawners); } @Override @@ -68,6 +81,9 @@ protected void drawFixed() { // decorations this.shop.getShopOptions().getShopDisplay().getDecoration().forEach((slot, item) -> setItem(slot, QuickItem.bg(item))); + // cart + drawCart(); + // search setButton(this.shop.getShopOptions().getShopDisplay().getSearchButtonSlot(), QuickItem .of(Settings.GUI_SHOP_CONTENT_ITEMS_SEARCH.getItemStack()) @@ -85,20 +101,24 @@ public void onExit(Player player) { @Override public boolean onResult(String string) { - click.manager.showGUI(click.player, new ShopContentsGUI(ShopContentsGUI.this.parent, click.player, ShopContentsGUI.this.shop, string)); + click.manager.showGUI(click.player, new ShopContentsGUI(ShopContentsGUI.this.parent, click.player, ShopContentsGUI.this.shop, string, false)); return true; } }; if (click.clickType == ClickType.RIGHT) - click.manager.showGUI(click.player, new ShopContentsGUI(ShopContentsGUI.this.parent, click.player, ShopContentsGUI.this.shop, null)); + click.manager.showGUI(click.player, new ShopContentsGUI(ShopContentsGUI.this.parent, click.player, ShopContentsGUI.this.shop, null, false)); }); - // cart - drawCart(); + if (!this.fromSpawners) { + // sell drop box + drawSell(); + } + // filter drawFilter(); + } private void drawFilter() { @@ -126,6 +146,18 @@ private void drawCart() { } + private void drawSell() { + setButton(this.shop.getShopOptions().getShopDisplay().getSellButtonSlot(), QuickItem + .of(Settings.GUI_SHOP_CONTENT_ITEMS_SELL.getItemStack()) + .name(TranslationManager.string(this.player, Translations.GUI_SHOP_CONTENTS_ITEMS_SELL_NAME)) + .lore(TranslationManager.list(this.player, Translations.GUI_SHOP_CONTENTS_ITEMS_SELL_LORE)) + .make(), click -> { + + click.manager.showGUI(click.player, new ShopQuickSellGUI(click.player, this.shop)); + }); + } + + @Override protected ItemStack makeDisplayItem(ShopContent content) { return content.generateDisplayItem(ShopContentDisplayType.LIVE_SHOP); @@ -134,7 +166,7 @@ protected ItemStack makeDisplayItem(ShopContent content) { @Override protected void onClick(ShopContent content, GuiClickEvent click) { if (click.clickType == ClickType.LEFT) - click.manager.showGUI(click.player, new ShopCheckoutGUI(this, player, this.shop, new CartItem(content, content.getMinimumPurchaseQty()))); + click.manager.showGUI(click.player, new ShopCheckoutGUI(this, player, this.shop, new CartItem(content, content.getMinimumPurchaseQty()), this.fromSpawners)); if (click.clickType == ClickType.RIGHT) { this.cart.addItem(content); diff --git a/src/main/java/ca/tweetzy/shops/gui/user/ShopQuickSellGUI.java b/src/main/java/ca/tweetzy/shops/gui/user/ShopQuickSellGUI.java new file mode 100644 index 0000000..12f03f6 --- /dev/null +++ b/src/main/java/ca/tweetzy/shops/gui/user/ShopQuickSellGUI.java @@ -0,0 +1,146 @@ +package ca.tweetzy.shops.gui.user; + +import ca.tweetzy.flight.comp.enums.CompMaterial; +import ca.tweetzy.flight.gui.helper.InventoryBorder; +import ca.tweetzy.flight.settings.TranslationManager; +import ca.tweetzy.flight.utils.Common; +import ca.tweetzy.flight.utils.PlayerUtil; +import ca.tweetzy.flight.utils.QuickItem; +import ca.tweetzy.shops.Shops; +import ca.tweetzy.shops.api.Transaction; +import ca.tweetzy.shops.api.events.ShopTransactionEvent; +import ca.tweetzy.shops.api.shop.Shop; +import ca.tweetzy.shops.gui.ShopsBaseGUI; +import ca.tweetzy.shops.impl.ShopTransaction; +import ca.tweetzy.shops.impl.shop.ItemShopContent; +import ca.tweetzy.shops.model.ItemParser; +import ca.tweetzy.shops.model.NumberHelper; +import ca.tweetzy.shops.model.Taxer; +import ca.tweetzy.shops.settings.Settings; +import ca.tweetzy.shops.settings.Translations; +import lombok.NonNull; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.IntStream; + +public final class ShopQuickSellGUI extends ShopsBaseGUI { + + private final Shop shop; + + public ShopQuickSellGUI(@NonNull Player player, @NonNull final Shop shop) { + super(null, player, TranslationManager.string(Translations.GUI_SHOP_QUICK_SELL_TITLE, "shop_name", shop.getDisplayName())); + this.shop = shop; + + setAcceptsItems(true); + InventoryBorder.getInsideBorders(6).forEach(this::setUnlocked); + + setOnClose(close -> attemptSell(close.player)); + + draw(); + } + + @Override + protected void draw() { + + Settings.GUI_SHOPS_QUICK_SELL_DECORATIONS.getStringList().forEach(itemLine -> { + final Map> keyed = ItemParser.parseString(itemLine); + + String item = keyed.get("item").get(0); + if (keyed.containsKey("model")) + item += ":" + keyed.get("model").get(0); + + List possibleSlots = new ArrayList<>(); + final String rawSlots = keyed.get("slot").get(0); + if (rawSlots.contains("-")) { + final String[] slotSplit = rawSlots.split("-"); + possibleSlots.addAll(IntStream.rangeClosed(Integer.parseInt(slotSplit[0]), Integer.parseInt(slotSplit[1])).boxed().toList()); + } else { + possibleSlots.add(Integer.parseInt(rawSlots)); + } + + for (Integer possibleSlot : possibleSlots) { + setItem(possibleSlot, QuickItem.bg(QuickItem.of(item).tag("ShopsBorderDeco", "Y").make())); + } + + }); + + setButton(5, 4, QuickItem + .of(CompMaterial.LIME_DYE) + .name(TranslationManager.string(Translations.GUI_SHOP_QUICK_SELL_ITEMS_SELL_NAME)) + .lore(TranslationManager.list(Translations.GUI_SHOP_QUICK_SELL_ITEMS_SELL_LORE)) + .make(), click -> attemptSell(click.player)); + + setButton(getBackExitButtonSlot(), getBackButton(), click -> { + gatherItems().forEach(item -> PlayerUtil.giveItem(click.player, item)); + + click.manager.showGUI(click.player, new ShopContentsGUI(new ShopsMainGUI(null, player), player, shop)); + }); + } + + private List gatherItems() { + List items = new ArrayList<>(); + InventoryBorder.getInsideBorders(6).forEach(slot -> { + final ItemStack slotItem = getItem(slot); + if (slotItem == null || slotItem.getType() == CompMaterial.AIR.parseMaterial()) return; + items.add(slotItem); + }); + return items; + } + + private void attemptSell(@NonNull final Player player) { + List itemShopContents = this.shop.getContent().stream().filter(content -> content instanceof ItemShopContent).map(content -> (ItemShopContent) content).toList(); + List items = gatherItems(); + + InventoryBorder.getInsideBorders(6).forEach(slot -> setItem(slot, CompMaterial.AIR.parseItem())); + + items.forEach(item -> { + final ItemShopContent shopContent = itemShopContents.stream().filter(content -> content.getItem().isSimilar(item)).findFirst().orElse(null); + if (shopContent == null || !shopContent.isAllowSell()) { + PlayerUtil.giveItem(player, item); + return; + } + + final int amountToSell = item.getAmount(); + final double subTotal = shopContent.getSellPrice() * amountToSell; + final double total = Settings.TAX_SELL.getBoolean() ? subTotal - Taxer.calculateTaxAmount(subTotal) : subTotal; + + String moneyAddMsg = ""; + + if (shopContent.isCurrencyOfItem()) { + Shops.getCurrencyManager().deposit(player, shopContent.getCurrencyItem(), (int) total); + moneyAddMsg += ((int) total) + " " + shopContent.getCurrencyDisplayName(); + } else { + final String[] currencySplit = shopContent.getCurrency().split("/"); + Shops.getCurrencyManager().deposit(player, currencySplit[0], currencySplit[1], total); + moneyAddMsg += NumberHelper.format(total); + } + + // show them msg + Common.tell(player, TranslationManager.string(player, Translations.MONEY_ADD, "currency", moneyAddMsg)); + + final Transaction transaction = new ShopTransaction( + UUID.randomUUID(), + shopContent.getId(), + shopContent.getShopId(), + shopContent.getOwningShop().getDisplayName(), + Transaction.TransactionType.SELL, + shopContent.getType(), + player.getUniqueId(), + player.getName(), + shopContent.getRawItem(), + shopContent.getCurrencyDisplayName(), + shopContent.isCurrencyOfItem() ? (int) total : total, + amountToSell, + System.currentTimeMillis() + ); + + final ShopTransactionEvent transactionEvent = new ShopTransactionEvent(transaction); + Shops.getInstance().getServer().getPluginManager().callEvent(transactionEvent); + }); + } +} diff --git a/src/main/java/ca/tweetzy/shops/impl/currency/EcoBitsCurrency.java b/src/main/java/ca/tweetzy/shops/impl/currency/EcoBitsCurrency.java new file mode 100644 index 0000000..894f923 --- /dev/null +++ b/src/main/java/ca/tweetzy/shops/impl/currency/EcoBitsCurrency.java @@ -0,0 +1,51 @@ +package ca.tweetzy.shops.impl.currency; + +import ca.tweetzy.flight.comp.enums.CompMaterial; +import ca.tweetzy.shops.api.currency.IconableCurrency; +import com.willfp.ecobits.currencies.Currencies; +import com.willfp.ecobits.currencies.Currency; +import com.willfp.ecobits.currencies.CurrencyUtils; +import org.bukkit.OfflinePlayer; + +import java.math.BigDecimal; + +public final class EcoBitsCurrency extends IconableCurrency { + + private final Currency currency; + + public EcoBitsCurrency(String currencyName) { + super("EcoBits", currencyName, "", CompMaterial.PAPER.parseItem()); + this.currency = Currencies.getByID(currencyName.toLowerCase()); + + if (this.currency != null) { + setDisplayName(this.currency.getName()); + } + } + + @Override + public boolean has(OfflinePlayer player, double amount) { + if (this.currency == null) + return false; + + return CurrencyUtils.getBalance(player, currency).doubleValue() >= amount; + } + + @Override + public boolean withdraw(OfflinePlayer player, double amount) { + if (this.currency == null) + return false; + + CurrencyUtils.setBalance(player, currency, BigDecimal.valueOf(CurrencyUtils.getBalance(player, currency).doubleValue() - amount)); + return true; + } + + @Override + public boolean deposit(OfflinePlayer player, double amount) { + if (this.currency == null) + return false; + + CurrencyUtils.setBalance(player, currency, BigDecimal.valueOf(CurrencyUtils.getBalance(player, currency).doubleValue() + amount)); + return true; + } +} + diff --git a/src/main/java/ca/tweetzy/shops/impl/manager/CurrencyManager.java b/src/main/java/ca/tweetzy/shops/impl/manager/CurrencyManager.java index fb9bb9c..e773818 100644 --- a/src/main/java/ca/tweetzy/shops/impl/manager/CurrencyManager.java +++ b/src/main/java/ca/tweetzy/shops/impl/manager/CurrencyManager.java @@ -5,6 +5,7 @@ import ca.tweetzy.shops.api.manager.ListManager; import ca.tweetzy.shops.impl.currency.ItemCurrency; import ca.tweetzy.shops.impl.currency.VaultCurrency; +import ca.tweetzy.shops.model.currency.EcoBitsEconomyLoader; import ca.tweetzy.shops.model.currency.FundsEconomyLoader; import ca.tweetzy.shops.model.currency.UltraEconomyLoader; import ca.tweetzy.shops.settings.Settings; @@ -80,5 +81,8 @@ public void load() { if (Bukkit.getServer().getPluginManager().isPluginEnabled("Funds")) new FundsEconomyLoader().getCurrencies().forEach(this::add); + + if (Bukkit.getServer().getPluginManager().isPluginEnabled("EcoBits")) + new EcoBitsEconomyLoader().getCurrencies().forEach(this::add); } } diff --git a/src/main/java/ca/tweetzy/shops/impl/shop/ShopLayout.java b/src/main/java/ca/tweetzy/shops/impl/shop/ShopLayout.java index 753e176..636a9cb 100644 --- a/src/main/java/ca/tweetzy/shops/impl/shop/ShopLayout.java +++ b/src/main/java/ca/tweetzy/shops/impl/shop/ShopLayout.java @@ -27,13 +27,14 @@ public final class ShopLayout implements ShopDisplay { private int searchButtonSlot; private int filterButtonSlot; private int cartButtonSlot; + private int sellButtonSlot; private List fillSlots; private Map decorations; private ItemStack background; public ShopLayout() { - this(6, 45, 48, 50, 49, 52, 53, InventoryBorder.getInsideBorders(6), new HashMap<>(), QuickItem.bg(CompMaterial.BLACK_STAINED_GLASS_PANE.parseItem())); + this(6, 45, 48, 50, 49, 52, 53,47, InventoryBorder.getInsideBorders(6), new HashMap<>(), QuickItem.bg(CompMaterial.BLACK_STAINED_GLASS_PANE.parseItem())); } @Override @@ -106,6 +107,16 @@ public void setCartButtonSlot(int slot) { this.cartButtonSlot = slot; } + @Override + public int getSellButtonSlot() { + return this.sellButtonSlot; + } + + @Override + public void setSellButtonSlot(int slot) { + this.sellButtonSlot = slot; + } + @Override public List getFillSlots() { return this.fillSlots; @@ -146,6 +157,7 @@ public String getJSONString() { object.addProperty("filterButtonSlot", this.filterButtonSlot); object.addProperty("searchButtonSlot", this.searchButtonSlot); object.addProperty("cartButtonSlot", this.cartButtonSlot); + object.addProperty("sellButtonSlot", this.sellButtonSlot); object.addProperty("rows", this.rows); final JsonArray fillSlotsArray = new JsonArray(); @@ -192,6 +204,7 @@ public static ShopLayout decodeJSON(@NonNull final String json) { parentObject.get("searchButtonSlot").getAsInt(), parentObject.get("filterButtonSlot").getAsInt(), parentObject.has("cartButtonSlot") ? parentObject.get("cartButtonSlot").getAsInt() : 53, + parentObject.has("sellButtonSlot") ? parentObject.get("sellButtonSlot").getAsInt() : 47, fillSlots, decoration, SerializeUtil.decodeItem(parentObject.get("backgroundItem").getAsString()) diff --git a/src/main/java/ca/tweetzy/shops/model/currency/EcoBitsEconomyLoader.java b/src/main/java/ca/tweetzy/shops/model/currency/EcoBitsEconomyLoader.java new file mode 100644 index 0000000..d79a3bc --- /dev/null +++ b/src/main/java/ca/tweetzy/shops/model/currency/EcoBitsEconomyLoader.java @@ -0,0 +1,43 @@ +package ca.tweetzy.shops.model.currency; + +import ca.tweetzy.shops.api.currency.AbstractCurrency; +import ca.tweetzy.shops.impl.currency.EcoBitsCurrency; +import ca.tweetzy.shops.settings.Settings; +import com.willfp.ecobits.currencies.Currencies; +import com.willfp.ecobits.currencies.Currency; + +import java.util.ArrayList; +import java.util.List; + +public final class EcoBitsEconomyLoader extends CurrencyLoader { + + public EcoBitsEconomyLoader() { + super("EcoBits"); + } + + + @Override + public List getCurrencies() { + final List currencies = new ArrayList<>(); + + for (Currency currency : Currencies.values()) { + boolean blackListed = false; + + for (String blacklisted : Settings.CURRENCY_BLACKLISTED.getStringList()) { + final String[] blacklistSplit = blacklisted.split(":"); + + if (blacklistSplit.length != 2) continue; + if (!blacklistSplit[0].equalsIgnoreCase(this.owningPlugin)) continue; + + if (blacklistSplit[1].equalsIgnoreCase(currency.getName())) + blackListed = true; + + } + + if (!blackListed) + currencies.add(new EcoBitsCurrency(currency.getId())); + } + + return currencies; + } +} diff --git a/src/main/java/ca/tweetzy/shops/settings/Settings.java b/src/main/java/ca/tweetzy/shops/settings/Settings.java index 74b11dd..5485329 100644 --- a/src/main/java/ca/tweetzy/shops/settings/Settings.java +++ b/src/main/java/ca/tweetzy/shops/settings/Settings.java @@ -21,6 +21,8 @@ public final class Settings extends FlightSettings { public static ConfigEntry TAX_ENABLED = create("settings.tax.enabled", false).withComment("If true, will apply sales tax to the total when a user is buying an item"); public static ConfigEntry TAX_AMOUNT = create("settings.tax.percentage", 13.0).withComment("The tax percentage. By default it's 13%"); public static ConfigEntry TAX_SELL = create("settings.tax.tax on sell", false).withComment("If true, selling items to a shop will remove tax percentage"); + public static ConfigEntry GLOBAL_GUI_CLICK_DELAY = create("settings.click delays.global", 1000).withComment("In milliseconds, how long should the delay between clicks be (set to -1 to disable)"); + public static ConfigEntry SEND_CLICK_DELAY_MSG = create("settings.send click delay message", false).withComment("Should shops tell the player to slow down? Or just send nothing."); /* ========================= GUI STUFF ========================= @@ -49,6 +51,19 @@ public final class Settings extends FlightSettings { "slot:44 item:BLACK_STAINED_GLASS_PANE" ), "TBD"); + public static ConfigEntry GUI_SHOPS_QUICK_SELL_DECORATIONS = create("gui.shops quick sell.decorations", List.of( + "slot:0-8 item:BLACK_STAINED_GLASS_PANE", + "slot:45-53 item:BLACK_STAINED_GLASS_PANE", + "slot:9 item:BLACK_STAINED_GLASS_PANE", + "slot:18 item:BLACK_STAINED_GLASS_PANE", + "slot:27 item:BLACK_STAINED_GLASS_PANE", + "slot:36 item:BLACK_STAINED_GLASS_PANE", + "slot:17 item:BLACK_STAINED_GLASS_PANE", + "slot:26 item:BLACK_STAINED_GLASS_PANE", + "slot:35 item:BLACK_STAINED_GLASS_PANE", + "slot:44 item:BLACK_STAINED_GLASS_PANE" + ), "TBD"); + public static ConfigEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_EXIT = create("gui.layout control picker.items.exit.item", CompMaterial.BARRIER.name()); public static ConfigEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_PREV_PAGE = create("gui.layout control picker.items.prev page.item", CompMaterial.ARROW.name()); @@ -56,10 +71,13 @@ public final class Settings extends FlightSettings { public static ConfigEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_SEARCH = create("gui.layout control picker.items.search.item", CompMaterial.DARK_OAK_SIGN.name()); public static ConfigEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_FILTER = create("gui.layout control picker.items.filter.item", CompMaterial.REPEATER.name()); public static ConfigEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_CART = create("gui.layout control picker.items.cart.item", CompMaterial.MINECART.name()); + public static ConfigEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_SELL = create("gui.layout control picker.items.sell.item", CompMaterial.ENDER_CHEST.name()); + public static ConfigEntry GUI_SHOP_CONTENT_ITEMS_SEARCH = create("gui.shop contents.items.review.item", CompMaterial.DARK_OAK_SIGN.name()); public static ConfigEntry GUI_SHOP_CONTENT_ITEMS_FILTER = create("gui.shop contents.items.filter.item", CompMaterial.REPEATER.name()); public static ConfigEntry GUI_SHOP_CONTENT_ITEMS_CART = create("gui.shop contents.items.cart.item", CompMaterial.MINECART.name()); + public static ConfigEntry GUI_SHOP_CONTENT_ITEMS_SELL = create("gui.shop contents.items.sell.item", CompMaterial.ENDER_CHEST.name()); public static ConfigEntry GUI_CHECKOUT_ITEMS_CHECKOUT = create("gui.checkout.items.checkout.item", CompMaterial.LIME_DYE.name()); diff --git a/src/main/java/ca/tweetzy/shops/settings/Translations.java b/src/main/java/ca/tweetzy/shops/settings/Translations.java index 27ba395..ee6f422 100644 --- a/src/main/java/ca/tweetzy/shops/settings/Translations.java +++ b/src/main/java/ca/tweetzy/shops/settings/Translations.java @@ -26,6 +26,7 @@ public Translations(@NonNull JavaPlugin plugin) { public static TranslationEntry ITEM_CANNOT_BE_AIR = create("error.item cannot be air", "&cYou cannot add air to the shop."); public static TranslationEntry CHECKOUT_NOT_MIN_QTY = create("error.checkout is not min qty", "&cYou must buy at least &fx&e%shop_item_purchase_qty% &cof this item!"); public static TranslationEntry NOT_ALLOWED_TO_USE_SHOP = create("error.no shop permission", "&cYou are not allowed to use that shop"); + public static TranslationEntry CLICKING_TOO_FAST = create("error.clicking too fast", "&cHey, you are clicking too fast, slow it down :)"); /* =================== INFORMATIONAL =================== @@ -33,8 +34,10 @@ public Translations(@NonNull JavaPlugin plugin) { public static TranslationEntry ADDED_ITEM_TO_SHOP = create("info.shop.add.item", "&aSuccessfully added &e%item_name% &ato &b%shop_id%"); public static TranslationEntry SHOP_IS_CLOSED = create("info.shop.closed", "&cThat shop is currently closed!"); public static TranslationEntry SHOP_DELETED = create("info.shop.deleted", "&aSuccessfully deleted that shop!"); + public static TranslationEntry UPDATED_SHOP_BG = create("info.shop.updated background", "&aSuccessfully updated the shop background!"); public static TranslationEntry MONEY_ADD = create("info.money.add", "&f&l+ &a&l%currency%"); public static TranslationEntry MONEY_REMOVE = create("info.money.remove", "&f&l- &c&l%currency%"); + public static TranslationEntry SELL_NOT_ALLOWED = create("info.checkout.sell not allowed", "&CThe sale of that item is not allowed!"); @@ -175,6 +178,22 @@ public Translations(@NonNull JavaPlugin plugin) { "&b&l%right_click% &7to add to cart" ); + public static final TranslationEntry GUI_CHECKOUT_ITEMS_SELL_NAME = create("gui.checkout.items.sell.name", "&LConfirm Sell"); + public static final TranslationEntry GUI_CHECKOUT_ITEMS_SELL_LORE = create("gui.checkout.items.sell.lore", + "&e&l%left_click% &7to sell now", + "&b&l%right_click% &7to add to cart" + ); + + public static final TranslationEntry GUI_CHECKOUT_ITEMS_TOGGLE_SELL_NAME = create("gui.checkout.items.toggle sell.name", "<oggle Sell/Buy"); + public static final TranslationEntry GUI_CHECKOUT_ITEMS_TOGGLE_SELL_LORE = create("gui.checkout.items.toggle sell.lore", + "&7Used to toggle sell/buy mode", + "", + "&7Buy Mode&f: %is_true%", + "", + "&e&lClick &7to toggle buy/sell mode" + ); + + public static final TranslationEntry GUI_CHECKOUT_ITEMS_INCR_NAME = create("gui.checkout.items.increment.name", "&a&l+%increment_value%"); public static final TranslationEntry GUI_CHECKOUT_ITEMS_INCR_LORE = create("gui.checkout.items.increment.lore", "&e&lClick &7to increment qty"); @@ -198,6 +217,16 @@ public Translations(@NonNull JavaPlugin plugin) { "&8&m------------------------------" ); + public static final TranslationEntry GUI_CHECKOUT_ITEMS_BREAKDOWN_SELL_LORE = create("gui.checkout.items.sell breakdown.lore", + "&8&m------------------------------", + "&7Selected Quantity&F: &e%checkout_item_qty%", + "", + "&A&lSell (Total)", + "&7Total&F: &a%checkout_item_sell_total%", + "", + "&8&m------------------------------" + ); + public static final TranslationEntry GUI_CHECKOUT_ITEMS_BREAKDOWN_LORE_HAS_TAX = create("gui.checkout.items.breakdown.has tax lore", "&eServer Tax Rate &F(&7%tax_rate%&a%&f)"); public static final TranslationEntry GUI_CHECKOUT_ITEMS_BREAKDOWN_LORE_NO_TAX = create("gui.checkout.items.breakdown.no tax lore", "&cNo tax is currently applied."); @@ -238,6 +267,13 @@ public Translations(@NonNull JavaPlugin plugin) { "&e%shop_item_description%" ); + public static final TranslationEntry GUI_SHOP_QUICK_SELL_TITLE = create("gui.shop quick sell.title", "%shop_name% &8> &7Quick Sell"); + public static final TranslationEntry GUI_SHOP_QUICK_SELL_ITEMS_SELL_NAME = create("gui.shop quick sell.items.sell.name", "&LSell Items"); + public static final TranslationEntry GUI_SHOP_QUICK_SELL_ITEMS_SELL_LORE = create("gui.shop quick sell.items.sell.lore", + "&e&lClick &7to confirm sell" + ); + + public static final TranslationEntry GUI_SHOP_EDIT_TITLE = create("gui.shop edit.title", "&lShops &8> &7Edit &8> &e%shop_id%"); public static final TranslationEntry GUI_SHOP_EDIT_ITEMS_ITEM_CONTENT_LORE = create("gui.shop edit.items.item content.lore", @@ -304,6 +340,14 @@ public Translations(@NonNull JavaPlugin plugin) { "&e&lClick &7to view your cart." ); + public static TranslationEntry GUI_SHOP_CONTENTS_ITEMS_SELL_NAME = create("gui.shop contents.items.sell.name", "&lSell Items"); + public static TranslationEntry GUI_SHOP_CONTENTS_ITEMS_SELL_LORE = create("gui.shop contents.items.sell.lore", + "&7Opens a quick sell menu to drop", + "&7any items this shop accepts to sell.", + "", + "&e&lClick &7to sell items." + ); + public static final TranslationEntry GUI_SHOP_CONTENTS_ITEMS_ITEM_CONTENT_BASE_LORE = create("gui.shop contents.items.content.lore.base lore", "&8&m------------------------------", "%shop_content_desc_info%", @@ -366,7 +410,10 @@ public Translations(@NonNull JavaPlugin plugin) { "&7How the shop content will be positioned,", "&7and any extra decoration items in the gui", "", - "&e&lClick &7to edit the layout/decoration" + "&e&l%left_click% &7to edit the layout/decoration", + "&b&l%right_click% &7with item to set background", + "&7If you right click with nothing it will set", + "&7the background item to nothing (AIR)" ); public static final TranslationEntry GUI_SHOP_SETTINGS_ITEMS_OPEN_NAME = create("gui.shop settings.items.open.name", "&lOpen/Close Shop"); @@ -623,6 +670,11 @@ public Translations(@NonNull JavaPlugin plugin) { "&7items from other shops." ); + public static TranslationEntry GUI_LAYOUT_EDITOR_ITEMS_SELL_NAME = create("gui.layout editor.items.sell.name", "&lSell"); + public static TranslationEntry GUI_LAYOUT_EDITOR_ITEMS_SELL_LORE = create("gui.layout editor.items.sell.lore", + "&7Used to quickly sell anything", + "&7that can be sold at this shop." + ); public static TranslationEntry GUI_LAYOUT_CONTROL_PICKER_TITLE = create("gui.layout control picker.title", "&EShops &f- &7Select Layout Control"); public static TranslationEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_EXIT_NAME = create("gui.layout control picker.items.exit.name", "&lExit Button"); @@ -661,8 +713,14 @@ public Translations(@NonNull JavaPlugin plugin) { "&e&l%left_click% &7to select this control" ); + public static TranslationEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_SELL_NAME = create("gui.layout control picker.items.sell.name", "&lSell Button"); + public static TranslationEntry GUI_LAYOUT_CONTROL_PICKER_ITEMS_SELL_LORE = create("gui.layout control picker.items.sell.lore", + "&7Used to quickly sell items at this shop.", + "&e&l%left_click% &7to select this control" + ); + public static void init() { - new Translations(Shops.getInstance()).setup(); + new Translations(Shops.getInstance()).setup(Shops.getInstance()); } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7c2d4be..d0bc093 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -7,4 +7,7 @@ api-version: 1.16 softdepend: - PlaceholderAPI - - Vault \ No newline at end of file + - Vault + - EcoBits + - Funds + - UltraEconomy \ No newline at end of file