From ea045524cdf13f5827297f860cf3ace16281c0da Mon Sep 17 00:00:00 2001 From: YuTian <2953516620@qq.com> Date: Sat, 19 Jul 2025 16:41:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=9A=E4=B8=AA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=BB=A5=E4=BF=AE=E6=94=B9=E9=85=8D=E7=BD=AE=E5=92=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8C=85=E6=8B=AC=20`.gitignore`?= =?UTF-8?q?=E3=80=81`AuMysteryDailyDeals.java`=E3=80=81`AuMysteryDailyDeal?= =?UTF-8?q?s.yml`=E3=80=81`Config.java`=E3=80=81`config.yml`=E3=80=81`PAPI?= =?UTF-8?q?Expansion.java`=E3=80=81`PlayerData.java`=E3=80=81`PlayerManage?= =?UTF-8?q?r.java`=E3=80=81`plugin.yml`=E3=80=81`pom.xml`=E3=80=81`ShopGui?= =?UTF-8?q?.java`=E3=80=81`ShopItem.java`=20=E5=92=8C=20`ShopItemManager.j?= =?UTF-8?q?ava`=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + pom.xml | 91 ++++++++ .../AuMysteryDailyDeals.java | 211 ++++++++++++++++++ .../aumysterydailydeals/config/Config.java | 55 +++++ .../aumysterydailydeals/data/PlayerData.java | 192 ++++++++++++++++ .../aumysterydailydeals/data/ShopItem.java | 50 +++++ .../aumysterydailydeals/gui/ShopGui.java | 154 +++++++++++++ .../manager/PlayerManager.java | 59 +++++ .../manager/ShopItemManager.java | 57 +++++ .../papi/PAPIExpansion.java | 35 +++ src/main/resources/config.yml | 5 + .../resources/lang/AuMysteryDailyDeals.yml | 17 ++ src/main/resources/plugin.yml | 10 + 13 files changed, 939 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/AuMysteryDailyDeals.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/config/Config.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/data/PlayerData.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/data/ShopItem.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/gui/ShopGui.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/manager/PlayerManager.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/manager/ShopItemManager.java create mode 100644 src/main/java/com/io/yutian/aumysterydailydeals/papi/PAPIExpansion.java create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/lang/AuMysteryDailyDeals.yml create mode 100644 src/main/resources/plugin.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b13d175 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.idea/ +/AuMysteryDailyDeals.iml +/target/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b1fea7e --- /dev/null +++ b/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + com.io.yutian + AuMysteryDailyDeals + 1.0-SNAPSHOT + jar + + AuMysteryDailyDeals + + + 1.8 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + + + + src/main/resources + true + + + + + + + public-rpg + https://repo.aurora-pixels.com/repository/public-rpg/ + + + + + + org.spigotmc + spigot-api + 1.12.2 + + + me.Demon.DemonPlugin + DemonAPI + 2.2.9 + + + me.clip.placeholderapi + PlaceholderAPI + 2.9.2 + + + com.io.yaohun.itemlibrary + AuItemStackLibrary + 1.5.2 + + + me.Demon.DemonCoins + DemonCoins + 2.0.5 + + + com.io.yutian.rainlib + RainLib + 1.0.2 + + + diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/AuMysteryDailyDeals.java b/src/main/java/com/io/yutian/aumysterydailydeals/AuMysteryDailyDeals.java new file mode 100644 index 0000000..b1f982c --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/AuMysteryDailyDeals.java @@ -0,0 +1,211 @@ +package com.io.yutian.aumysterydailydeals; + +import com.io.yutian.aumysterydailydeals.config.Config; +import com.io.yutian.aumysterydailydeals.data.PlayerData; +import com.io.yutian.aumysterydailydeals.data.ShopItem; +import com.io.yutian.aumysterydailydeals.gui.ShopGui; +import com.io.yutian.aumysterydailydeals.manager.PlayerManager; +import com.io.yutian.aumysterydailydeals.manager.ShopItemManager; +import com.io.yutian.aumysterydailydeals.papi.PAPIExpansion; +import me.Demon.DemonPlugin.DemonAPI; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public final class AuMysteryDailyDeals extends JavaPlugin { + + private static AuMysteryDailyDeals instance; + + @Override + public void onEnable() { + instance = this; + + if (Bukkit.getServer().getPluginManager().getPlugin("PlaceholderAPI") != null){ + new PAPIExpansion().register(); + } + + Config.reload(); + ShopItemManager.reload(); + + Bukkit.getScheduler().runTaskTimer(this, () -> { + for (Player player : Bukkit.getOnlinePlayers()) { + PlayerData data = PlayerManager.getPlayerData(player.getName()); + data.refreshIfNeeded(); + } + }, 0L, 20L * 60); + + } + + @Override + public void onDisable() { + PlayerManager.saveAll(); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!sender.isOp()) return true; + + if (args.length == 0) { + sender.sendMessage("§e------- ======= §6每日神秘折扣商店 §e======= -------"); + sender.sendMessage("§2/" + label + " open §f- §2打开界面"); + sender.sendMessage("§2/" + label + " info §e[玩家] §f- §2查看玩家信息"); + sender.sendMessage("§2/" + label + " setdiscount §e[玩家] §e[折扣] §f- §2设置玩家折扣"); + sender.sendMessage("§2/" + label + " setitems §e[玩家] §e[shopItems...] §f- §2设置玩家商店物品(填写物品Id,用,分隔)"); + sender.sendMessage("§2/" + label + " setbuyamount §e[玩家] §e[itemId] §e[数量] §f- §2设置玩家购买数量"); + sender.sendMessage("§2/" + label + " reload §f- §2重载配置文件"); + sender.sendMessage("§e------- ======= §6每日神秘折扣商店 §e======= -------"); + return true; + } + + String sub = args[0].toLowerCase(); + + if (sub.equals("reload")) { + Config.reload(); + ShopItemManager.reload(); + PlayerManager.reload(); + DemonAPI.sendMessage(sender, "§a插件已重载"); + return true; + } else if (sub.equals("open")) { + if (!(sender instanceof Player)) { + sender.sendMessage("§c只有玩家可以打开商店界面"); + return true; + } + Player player = (Player) sender; + new ShopGui(player).open(); + return true; + } else if (sub.equals("info")) { + if (args.length < 2) { + DemonAPI.sendMessage(sender, "§c用法: /" + label + " info <玩家名>"); + return true; + } + String name = args[1]; + PlayerData data = PlayerManager.getPlayerData(name); + sender.sendMessage("§e[玩家: §a" + name + "§e]"); + sender.sendMessage("§6折扣: §b" + data.getDiscount() + " 折"); + sender.sendMessage("§6商店物品: §b"+String.join(", ", data.getItems().stream().map(ShopItem::getItemId).toArray(String[]::new))); + sender.sendMessage("§6购买记录: "+(data.getBuyAmounts().isEmpty() ? "§b无" : "")); + for (String itemId : data.getBuyAmounts().keySet()) { + int amount = data.getBuyAmounts().get(itemId); + sender.sendMessage("§b" + itemId + " §6- §b" + amount); + } + return true; + } else if (sub.equals("setdiscount")) { + if (args.length < 3) { + DemonAPI.sendMessage(sender,"§c用法: /" + label + " setdiscount <玩家名> <折扣>"); + return true; + } + try { + String name = args[1]; + double discount = Double.parseDouble(args[2]); + if (discount <= 0 || discount > 10) { + DemonAPI.sendMessage(sender,"§c折扣范围应为 0~10(折)"); + return true; + } + PlayerData data = PlayerManager.getPlayerData(name); + data.setDiscount(discount); + data.save(); + DemonAPI.sendMessage(sender,"§a已设置 §e" + name + " §a的折扣为 §e" + discount + " 折"); + } catch (NumberFormatException e) { + DemonAPI.sendMessage(sender,"§c折扣格式错误,应为小数,如 6.5"); + } + return true; + } else if (sub.equals("setitems")) { + if (args.length < 3) { + DemonAPI.sendMessage(sender,"§c用法: /" + label + " setitems <玩家名> "); + return true; + } + String name = args[1]; + String[] itemIds = args[2].split(","); + List items = new ArrayList<>(); + int added = 0; + for (String id : itemIds) { + ShopItem shopItem = ShopItemManager.getShopItem(id.trim()); + if (shopItem != null) { + items.add(shopItem); + added++; + } else { + DemonAPI.sendMessage(sender,"§c无效的物品ID: §e" + id); + } + } + PlayerData data = PlayerManager.getPlayerData(name); + data.setItems(items); + data.save(); + DemonAPI.sendMessage(sender,"§a已为玩家 §e" + name + " §a设置 §e" + added + " §a个商店物品"); + return true; + } else if (sub.equalsIgnoreCase("setbuyamount")) { + if (args.length < 4) { + DemonAPI.sendMessage(sender,"§c用法: /" + label + " setbuyamount <玩家名> <数量>"); + return true; + } + try { + String name = args[1]; + String itemId = args[2]; + int amount = Integer.parseInt(args[3]); + PlayerData data = PlayerManager.getPlayerData(name); + data.getBuyAmounts().put(itemId, amount); + data.save(); + DemonAPI.sendMessage(sender,"§a已设置 §e" + name + " §a的 §e" + itemId + " §a购买次数为 §e" + amount); + } catch (NumberFormatException e) { + DemonAPI.sendMessage(sender,"§c数量必须为整数"); + } + return true; + } + DemonAPI.sendMessage(sender,"§c未知指令, 使用 /" + label + " 查看帮助"); + return true; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + if (!sender.isOp()) return Collections.emptyList(); + + if (args.length == 1) { + return Arrays.asList("open", "info", "setdiscount", "setitems", "setbuyamount", "reload").stream() + .filter(s -> s.startsWith(args[0].toLowerCase())) + .collect(Collectors.toList()); + } + + String sub = args[0].toLowerCase(); + + if (args.length == 2) { + switch (sub) { + case "info": + case "setdiscount": + case "setitems": + case "setbuyamount": + return Bukkit.getOnlinePlayers().stream() + .map(Player::getName) + .filter(name -> name.toLowerCase().startsWith(args[1].toLowerCase())) + .collect(Collectors.toList()); + } + } + + if (args.length == 3) { + if (sub.equals("setdiscount")) { + return Arrays.asList("9", "8.5", "7", "6.5", "5", "3.5", "1"); + } else if (sub.equals("setitems") || sub.equals("setbuyamount")) { + return ShopItemManager.getShopItems().keySet().stream() + .filter(id -> id.toLowerCase().startsWith(args[2].toLowerCase())) + .collect(Collectors.toList()); + } + } + + if (args.length == 4 && sub.equals("setbuyamount")) { + return Arrays.asList("0", "1", "2", "3", "5", "10"); + } + + return Collections.emptyList(); + } + + + public static AuMysteryDailyDeals inst() { + return instance; + } +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/config/Config.java b/src/main/java/com/io/yutian/aumysterydailydeals/config/Config.java new file mode 100644 index 0000000..2e302a8 --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/config/Config.java @@ -0,0 +1,55 @@ +package com.io.yutian.aumysterydailydeals.config; + +import com.io.yutian.aumysterydailydeals.AuMysteryDailyDeals; +import me.Demon.DemonPlugin.DemonAPI; +import me.Demon.DemonPlugin.data.LangData; +import org.bukkit.configuration.file.FileConfiguration; + +public class Config { + + private static LangData langData; + + private static double minDiscount = 5.0; + private static double maxDiscount = 9.9; + + private static int playerShopItemAmount = 6; //玩家商店物品数量 + private static int refreshCost = 10; //刷新所需软妹币 + private static int refreshCount = 1; //每日刷新次数 + + public static void reload() { + langData = DemonAPI.getLangData(AuMysteryDailyDeals.inst().getName()); + AuMysteryDailyDeals.inst().saveDefaultConfig(); + AuMysteryDailyDeals.inst().reloadConfig(); + FileConfiguration config = AuMysteryDailyDeals.inst().getConfig(); + minDiscount = config.getDouble("min-discount", 5.0); + maxDiscount = config.getDouble("max-discount", 9.9); + playerShopItemAmount = config.getInt("player-shop-item-amount", 6); + refreshCost = config.getInt("refresh-cost", 10); + refreshCount = config.getInt("refresh-count", 1); + } + + public static LangData getLangData() { + return langData; + } + + public static double getMinDiscount() { + return minDiscount; + } + + public static double getMaxDiscount() { + return maxDiscount; + } + + public static int getPlayerShopItemAmount() { + return playerShopItemAmount; + } + + public static int getRefreshCost() { + return refreshCost; + } + + public static int getRefreshCount() { + return refreshCount; + } + +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/data/PlayerData.java b/src/main/java/com/io/yutian/aumysterydailydeals/data/PlayerData.java new file mode 100644 index 0000000..017162d --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/data/PlayerData.java @@ -0,0 +1,192 @@ +package com.io.yutian.aumysterydailydeals.data; + +import com.io.yutian.aumysterydailydeals.AuMysteryDailyDeals; +import com.io.yutian.aumysterydailydeals.config.Config; +import com.io.yutian.aumysterydailydeals.manager.ShopItemManager; +import com.io.yutian.rainlib.util.TimeUtil; +import me.Demon.DemonPlugin.Util.RandomUtil; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PlayerData { + + private final String name; + private File file; + private FileConfiguration configuration; + + private long lastUpdateTime; + private double discount; + private List items = new ArrayList<>(); + private Map buyAmounts = new HashMap<>(); + private int refreshCount; + + public PlayerData(String name) { + this.name = name; + File path = new File(AuMysteryDailyDeals.inst().getDataFolder(), "PlayerData"); + if (!path.exists()) { + path.mkdirs(); + } + this.file = new File(path, name + ".yml"); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + this.configuration = YamlConfiguration.loadConfiguration(file); + load(); + boolean changed = false; + if (this.items.isEmpty()) { + this.items = ShopItemManager.getRandomShopItems(Config.getPlayerShopItemAmount()); + changed = true; + } + if (this.discount == 10 || this.discount == 0) { + this.discount = RandomUtil.getRandomDouble(Config.getMinDiscount(), Config.getMaxDiscount(), 1); + changed = true; + } + if (changed) { + save(); + } + } + + public String getName() { + return name; + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + + public FileConfiguration getConfiguration() { + return configuration; + } + + public void setConfiguration(FileConfiguration configuration) { + this.configuration = configuration; + } + + public long getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(long lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public double getDiscount() { + return discount; + } + + public void setDiscount(double discount) { + this.discount = discount; + } + + public int getBuyAmount(String itemId) { + return buyAmounts.getOrDefault(itemId, 0); + } + + public Map getBuyAmounts() { + return buyAmounts; + } + + public void addBuyAmount(String itemId, int amount) { + this.buyAmounts.put(itemId, this.buyAmounts.getOrDefault(itemId, 0) + amount); + } + + public void setBuyAmounts(Map buyAmounts) { + this.buyAmounts = buyAmounts; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public int getRefreshCount() { + return refreshCount; + } + + public void setRefreshCount(int refreshCount) { + this.refreshCount = refreshCount; + } + + public void refresh() { + this.items = ShopItemManager.getRandomShopItems(Config.getPlayerShopItemAmount()); + this.buyAmounts.clear(); + this.refreshCount++; + } + + public void refreshIfNeeded() { + if (TimeUtil.isNewDay(this.lastUpdateTime)) { + this.lastUpdateTime = System.currentTimeMillis(); + this.items = ShopItemManager.getRandomShopItems(Config.getPlayerShopItemAmount()); + this.discount = RandomUtil.getRandomDouble(Config.getMinDiscount(), Config.getMaxDiscount(), 1); + this.buyAmounts.clear(); + this.refreshCount = 0; + save(); + } + } + + private void load() { + this.lastUpdateTime = configuration.getLong("lastUpdateTime", 0); + this.discount = configuration.getDouble("discount", 10); + this.refreshCount = configuration.getInt("refreshCount", Config.getRefreshCount()); + this.items = new ArrayList<>(); + if (configuration.contains("items")) { + List list = configuration.getStringList("items"); + for (String itemId : list) { + ShopItem shopItem = ShopItemManager.getShopItem(itemId); + if (shopItem == null) { + Bukkit.getLogger().severe("[每日折扣神秘商店] 加载玩家数据出现问题 " + name + " 原因: 商店物品 " + itemId + " 不存在"); + continue; + } + this.items.add(shopItem); + } + } + if (configuration.getConfigurationSection("buyAmounts") != null) { + ConfigurationSection section = configuration.getConfigurationSection("buyAmounts"); + for (String key : section.getKeys(false)) { + buyAmounts.put(key, section.getInt(key)); + } + } + refreshIfNeeded(); + } + + public void save() { + configuration.set("lastUpdateTime", this.lastUpdateTime); + configuration.set("discount", this.discount); + List itemList = new ArrayList<>(); + for (ShopItem item : items) { + itemList.add(item.getId()); + } + configuration.set("items", itemList); + configuration.set("buyAmounts", null); + for (Map.Entry entry : buyAmounts.entrySet()) { + configuration.set("buyAmounts." + entry.getKey(), entry.getValue()); + } + configuration.set("refreshCount", this.refreshCount); + try { + configuration.save(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/data/ShopItem.java b/src/main/java/com/io/yutian/aumysterydailydeals/data/ShopItem.java new file mode 100644 index 0000000..1ad06d3 --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/data/ShopItem.java @@ -0,0 +1,50 @@ +package com.io.yutian.aumysterydailydeals.data; + +import org.bukkit.configuration.ConfigurationSection; + +public class ShopItem { + + private String id; + private String itemId; + private int amount; + private int buyAmount; + private int coins; + + public ShopItem(String id, String itemId, int amount, int buyAmount, int coins) { + this.id = id; + this.itemId = itemId; + this.amount = amount; + this.buyAmount = buyAmount; + this.coins = coins; + } + + public static ShopItem load(String id, ConfigurationSection section) { + + String itemId = section.getString("itemId"); + int amount = section.getInt("amount"); + int buyAmount = section.getInt("buyAmount"); + int coins = section.getInt("coins"); + return new ShopItem(id, itemId, amount, buyAmount, coins); + } + + public String getId() { + return id; + } + + public String getItemId() { + return itemId; + } + + public int getAmount() { + return amount; + } + + public int getBuyAmount() { + return buyAmount; + } + + public int getCoins() { + return coins; + } + +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/gui/ShopGui.java b/src/main/java/com/io/yutian/aumysterydailydeals/gui/ShopGui.java new file mode 100644 index 0000000..65ae644 --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/gui/ShopGui.java @@ -0,0 +1,154 @@ +package com.io.yutian.aumysterydailydeals.gui; + +import com.io.yaohun.itemlibrary.api.ItemKuAPI; +import com.io.yutian.aumysterydailydeals.config.Config; +import com.io.yutian.aumysterydailydeals.data.PlayerData; +import com.io.yutian.aumysterydailydeals.data.ShopItem; +import com.io.yutian.aumysterydailydeals.manager.PlayerManager; +import com.io.yutian.rainlib.gui.Gui; +import com.io.yutian.rainlib.gui.button.Button; +import com.io.yutian.rainlib.util.ItemStackBuilder; +import com.io.yutian.rainlib.util.StringUtil; +import me.Demon.DemonCoins.util.CoinsAPI; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ShopGui extends Gui { + + private static Map guiMap = new HashMap<>(); + + private PlayerData playerData; + + public ShopGui(Player player) { + super(player, Config.getLangData().getMessage("Gui-Title"), 54); + playerData = PlayerManager.getPlayerData(player.getName()); + playerData.refreshIfNeeded(); + init(); + initButton(); + } + + @Override + public void open() { + super.open(); + guiMap.put(player, this); + } + + @Override + public void close(InventoryCloseEvent event) { + super.close(event); + guiMap.remove(player); + } + + @Override + public void init() { + int percentOff = (int) Math.round(100.0 - (playerData.getDiscount() * 10)); + addButton(0, new Button(new ItemStackBuilder(Material.SIGN) + .setDisplayName(StringUtil.formatIndexed(Config.getLangData().getMessage("Gui-Items-Info-Name"), playerData.getDiscount(), percentOff)) + .setLore(Arrays.asList( + Config.getLangData().getMessage("Gui-Items-Info-Lore-1") + )) + .build()).noSound()); + int i = 0; + for (ShopItem shopItem : playerData.getItems()) { + addButton(9 + i, buildShopItemButton(shopItem)); + i++; + } + int j = i / 9 * 9; + for (ShopItem shopItem : playerData.getItems()) { + addButton(18+j, buildBuyButton(shopItem)); + j++; + } + int k = (i / 9 * 9) + (j / 9 * 9); + addButton(27+k, new Button(new ItemStackBuilder(Material.CLAY_BALL) + .setDisplayName(Config.getLangData().getMessage("Gui-Items-Refresh-Name")) + .setLore(Arrays.asList( + Config.getLangData().getMessage("Gui-Items-Refresh-Lore-1"), + StringUtil.formatIndexed(Config.getLangData().getMessage("Gui-Items-Refresh-Lore-2"), Config.getRefreshCost()), + StringUtil.formatIndexed(Config.getLangData().getMessage("Gui-Items-Refresh-Lore-3"), Config.getRefreshCount()-playerData.getRefreshCount()) + )) + .build()).click((player1, clickType) -> { + if (playerData.getRefreshCount() >= Config.getRefreshCount()) { + player1.sendMessage(Config.getLangData().getMessage("Message-Refresh-Limit")); + return; + } + int playerCoins = CoinsAPI.getCoinsAmount(player1.getName()); + int cost = Config.getRefreshCost(); + if (playerCoins < cost) { + player1.sendMessage(Config.getLangData().getMessage("Message-Refresh-NotEnough")); + return; + } + CoinsAPI.removeCoinsPro(player1.getName(), cost); + playerData.refresh(); + playerData.save(); + PlayerManager.setPlayerData(player1.getName(), playerData); + init(); + initButton(); + player1.sendMessage(StringUtil.formatIndexed(Config.getLangData().getMessage("Message-Refresh-Success"), cost)); + })); + } + + private Button buildShopItemButton(ShopItem shopItem) { + ItemStack itemStack = ItemKuAPI.getItems(shopItem.getItemId(), shopItem.getAmount()); + ItemMeta itemMeta = itemStack.getItemMeta(); + List lores = itemMeta.getLore(); + lores.add(" "); + int newPrice = (int) Math.round(shopItem.getCoins() * (playerData.getDiscount() / 10)); + lores.add(StringUtil.formatIndexed(Config.getLangData().getMessage("Gui-Items-ShopItem-Lore-1"), shopItem.getCoins(), newPrice)); + if (shopItem.getBuyAmount() > 0) { + int playerBuyAmount = playerData.getBuyAmount(shopItem.getItemId()); + lores.add(StringUtil.formatIndexed(Config.getLangData().getMessage("Gui-Items-ShopItem-Lore-2"), playerBuyAmount, shopItem.getBuyAmount(), shopItem.getBuyAmount()-playerBuyAmount)); + } + itemMeta.setLore(lores); + itemStack.setItemMeta(itemMeta); + return new Button(itemStack).noSound(); + } + + private Button buildBuyButton(ShopItem shopItem) { + ItemStack itemStack = new ItemStackBuilder(Material.FIREWORK_CHARGE).setDisplayName(shopItem.getItemId()).build(); + + return new Button(itemStack).click((player1, clickType) -> { + int currentBuyAmount = playerData.getBuyAmount(shopItem.getItemId()); + int buyLimit = shopItem.getBuyAmount(); + + if (buyLimit > 0 && currentBuyAmount >= buyLimit) { + player1.sendMessage(Config.getLangData().getMessage("Message-Buy-Limit")); + return; + } + + int price = (int) Math.round(shopItem.getCoins() * (playerData.getDiscount() / 10)); + int playerCoins = CoinsAPI.getCoinsAmount(player1.getName()); + + if (playerCoins < price) { + player1.sendMessage(Config.getLangData().getMessage("Message-Buy-NotEnough")); + return; + } + + CoinsAPI.removeCoinsPro(player1.getName(), price); + + ItemStack reward = ItemKuAPI.getItems(shopItem.getItemId(), shopItem.getAmount()); + player1.getInventory().addItem(reward); + + playerData.addBuyAmount(shopItem.getItemId(), 1); + playerData.save(); + PlayerManager.setPlayerData(player1.getName(), playerData); + + init(); + initButton(); + + player1.sendMessage(StringUtil.formatIndexed(Config.getLangData().getMessage("Message-Buy-Success"), shopItem.getItemId(), price)); + }); + } + + public static Map getGuiMap() { + return guiMap; + } + +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/manager/PlayerManager.java b/src/main/java/com/io/yutian/aumysterydailydeals/manager/PlayerManager.java new file mode 100644 index 0000000..0b34681 --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/manager/PlayerManager.java @@ -0,0 +1,59 @@ +package com.io.yutian.aumysterydailydeals.manager; + +import com.io.yutian.aumysterydailydeals.data.PlayerData; +import com.io.yutian.aumysterydailydeals.gui.ShopGui; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class PlayerManager { + + private static Map playerDatas = new HashMap<>(); + + public static PlayerData getPlayerData(String playerName) { + if (!playerDatas.containsKey(playerName)) { + loadPlayerData(playerName); + } + return playerDatas.get(playerName); + } + + public static void loadPlayerData(String playerName) { + if (!playerDatas.containsKey(playerName)) { + playerDatas.put(playerName, new PlayerData(playerName)); + } + } + + public static void setPlayerData(String playerName, PlayerData playerData) { + playerDatas.put(playerName, playerData); + } + + public static void save(String playerName) { + if (!playerDatas.containsKey(playerName)) { + return; + } + PlayerData playerData = playerDatas.remove(playerName); + playerData.save(); + } + + public static void saveAll() { + for (PlayerData playerData : playerDatas.values()) { + playerData.save(); + } + } + + public static void reload() { + Set players = new HashSet<>(ShopGui.getGuiMap().keySet()); + for (Player player : players) { + player.closeInventory(); + } + playerDatas.clear(); + for (Player player : Bukkit.getOnlinePlayers()) { + loadPlayerData(player.getName()); + } + } + +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/manager/ShopItemManager.java b/src/main/java/com/io/yutian/aumysterydailydeals/manager/ShopItemManager.java new file mode 100644 index 0000000..2489ec4 --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/manager/ShopItemManager.java @@ -0,0 +1,57 @@ +package com.io.yutian.aumysterydailydeals.manager; + +import com.io.yutian.aumysterydailydeals.AuMysteryDailyDeals; +import com.io.yutian.aumysterydailydeals.data.ShopItem; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +public class ShopItemManager { + + private static Map shopItems = new HashMap<>(); + + public static List getRandomShopItems(int amount) { + List items = new ArrayList<>(); + for (ShopItem item : shopItems.values()) { + items.add(item); + } + List randomItems = new ArrayList<>(); + Collections.shuffle(items); + int limit = Math.min(amount, items.size()); + return new ArrayList<>(items.subList(0, limit)); + } + + public static ShopItem getShopItem(String name) { + return shopItems.get(name); + } + + public static void reload() { + shopItems.clear(); + File file = new File(AuMysteryDailyDeals.inst().getDataFolder(), "items.yml"); + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + FileConfiguration configuration = YamlConfiguration.loadConfiguration(file); + ConfigurationSection rootSection = configuration.getConfigurationSection("ShopItems"); + for (String key : rootSection.getKeys(false)) { + ConfigurationSection section = rootSection.getConfigurationSection(key); + ShopItem item = ShopItem.load(key, section); + shopItems.put(key, item); + } + Bukkit.getConsoleSender().sendMessage("§d[神秘折扣商店] §7加载商品: §6"+shopItems.size()+"个"); + } + + public static Map getShopItems() { + return shopItems; + } + +} diff --git a/src/main/java/com/io/yutian/aumysterydailydeals/papi/PAPIExpansion.java b/src/main/java/com/io/yutian/aumysterydailydeals/papi/PAPIExpansion.java new file mode 100644 index 0000000..0cd0b87 --- /dev/null +++ b/src/main/java/com/io/yutian/aumysterydailydeals/papi/PAPIExpansion.java @@ -0,0 +1,35 @@ +package com.io.yutian.aumysterydailydeals.papi; + +import com.io.yutian.aumysterydailydeals.AuMysteryDailyDeals; +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.entity.Player; + +public class PAPIExpansion extends PlaceholderExpansion { + + @Override + public String onPlaceholderRequest(Player p, String params) { + if (params.contains("_")) { + String[] array = params.split("_"); + System.out.println(params+":"+array[0]); + if (array.length == 2) { + } + } + return ""; + } + + @Override + public String getIdentifier() { + return "aumysterydailydeals"; + } + + @Override + public String getAuthor() { + return "SuperYuTian"; + } + + @Override + public String getVersion() { + return AuMysteryDailyDeals.inst().getDescription().getVersion(); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..9b55d03 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,5 @@ +min-discount: 5.0 +max-discount: 9.9 +player-shop-item-amoun: 6 +refresh-cost: 10 +refresh-count: 1 \ No newline at end of file diff --git a/src/main/resources/lang/AuMysteryDailyDeals.yml b/src/main/resources/lang/AuMysteryDailyDeals.yml new file mode 100644 index 0000000..583d897 --- /dev/null +++ b/src/main/resources/lang/AuMysteryDailyDeals.yml @@ -0,0 +1,17 @@ +Gui: + Gui-Title: "每日神祕折扣商店" + Gui-Items-Info-Name: "§6✦ 今日折扣 §8» §e{0}折 §a(-{1}%) §7(限時優惠)" + Gui-Items-Info-Lore-1: "§d折扣每日刷新~" + Gui-Items-ShopItem-Lore-1: "§6價格: §e{1} §f軟妹幣 §8(原價: §7§m{0} 軟妹幣§8)" + Gui-Items-ShopItem-Lore-2: "§6限購: §a{0}§8 / §7{1} §f(§e剩餘 §6{2} §f次)" + Gui-Items-Refresh-Name: "§a§l刷新商品" + Gui-Items-Refresh-Lore-1: "§7重新隨機生成今日可購買商品" + Gui-Items-Refresh-Lore-2: "§6花費: §e{0} §f軟妹幣" + Gui-Items-Refresh-Lore-3: "§6今日剩餘刷新次數: §a{0}" +Message: + Message-Buy-Success: "§a成功購買 §e{0}§a!花費 §e{1} §a軟妹幣。" + Message-Buy-Limit: "§c你今天已達到該商品的購買上限!" + Message-Buy-NotEnough: "§c你的軟妹幣不足,無法購買!" + Message-Refresh-NotEnough: "§c你的軟妹幣不足,無法刷新!" + Message-Refresh-Success: "§a成功刷新商店!花費 §e{0} §a軟妹幣。" + Message-Refresh-Limit: "§c你今天的刷新次數已用完,無法繼續刷新!" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..558abdb --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,10 @@ +name: AuMysteryDailyDeals +version: '1.0.2' +main: com.io.yutian.aumysterydailydeals.AuMysteryDailyDeals +depend: + - RainLib + - DemonAPI + - AuItemStackLibrary +commands: + aumysterydailydeals: + aliases: [amdd] \ No newline at end of file