commit ea045524cdf13f5827297f860cf3ace16281c0da
Author: YuTian <2953516620@qq.com>
Date: Sat Jul 19 16:41:18 2025 +0800
更新多个文件以修改配置和功能,包括 `.gitignore`、`AuMysteryDailyDeals.java`、`AuMysteryDailyDeals.yml`、`Config.java`、`config.yml`、`PAPIExpansion.java`、`PlayerData.java`、`PlayerManager.java`、`plugin.yml`、`pom.xml`、`ShopGui.java`、`ShopItem.java` 和 `ShopItemManager.java`。
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