• 欢迎加入MineBBS QQ讨论群:点击查看所有的官方讨论群
  • 我们将于近期对服务器进行迁移,服务可能中断至多2日。请各位安排好自己的访问计划,造成不便敬请谅解!
  • MineBBS入站考试已经上线!想要成为【正式会员】解锁更多功能吗?快来参与吧!【点我去看】
MuuDm 动态市场-重置版

原创 二次开发 付费 MuuDm 动态市场-重置版 1.0.0

请登录后获取
版权类型
原创
插件中文名称
动态市场
插件英文名称
MuuMD
原帖地址
#
支持的核心(服务端)
  1. Spigot
  2. Paper
  3. Purpur
  4. 其他核心
语言支持
中文(简体)
前置组件
Vault 必需 经济系统核心依赖
PlaceholderAPI 可选 提供占位符变量支持
WarZSafeBox 可选 保险箱物品价值统计 https://www.minebbs.com/resources/warzsafebox-mc.11399/
适配版本(Java)
  1. 1.21
  2. 1.20
  3. 1.19
  4. 1.18
动态定价引擎商品价格随供需实时波动,购买推高价格,出售压低价格,设有上下限保护机制防止极端波动。

库存与补货系统独立库存追踪,支持每日自动补货,可配置库存上限与补充数量。

税收调控买卖双向税收,有效回收服务器货币,控制经济通胀。

可视化界面分类导航、分页浏览、实时价格与库存显示,操作简洁直观。

数据持久化SQLite 本地存储,完整交易日志记录,配置热重载。

为什么选择我们?

真实经济体验供需定价机制让市场更具策略性,区别于传统固定价格商店。

零外部依赖仅需 Vault,无需 MySQL 等外部服务,开箱即用。

高度可配置价格波动率、税率、库存、音效等参数均可自定义调整。

轻量高效模块化架构,SQLite 存储,资源占用低,性能稳定。

指令说明
/muudm category <名称>创建分类 (需手持物品作为图标)
/muudm delcategory <名称>删除分类
/muudm add <价格> <是否可购买> [分类] [权重] [每日库存]添加手持物品到市场
/muudm setprice <价格>修改手持物品价格
/muudm setstock <库存>修改手持物品库存
/muudm remove从市场移除手持物品
/muudm reload重载配置文件
/muudm restock手动补充所有物品库存
/muudm list查看所有物品ID和材质名
/muudm export导出分类排序到配置
/muudm config打开物品配置GUI
UI图标为mod图标可以自行修改图标
1768308191930.webp

1768308241573.webp

1768308258535.webp

1768308272279.webp

1768308283253.webp

配置界面
1768308327084.webp

1768308338994.webp

可手动控制涨跌

代码:
# MuuDm 动态市场配置文件

# 税收设置
tax:
  buy: 0.1    # 购买税率 10%
  sell: 0.1   # 出售税率 10%

# 价格设置
price:
  buy-change-rate: 0.001   # 购买时价格上涨率 0.1%
  sell-change-rate: 0.002  # 出售时价格下跌率 0.2%
  # 价格波动限制(基于原始价格)
  max-rate: 1.2           # 价格上限:原始价格的 120%
  min-rate: 0.5           # 价格下限:原始价格的 50%
  # 管理员手动调价幅度(用于GUI配置界面)
  adjust-step: 5          # 每次调整的百分比,如 5 表示上涨/下跌 5%

# 每日价格上涨设置
daily-increase:
  enabled: true           # 是否启用每日价格上涨
  rate: 0.01              # 每日上涨率 1%
  hour: 0                 # 每天几点执行(0-23,0表示凌晨0点)

# 音效设置
sound:
  enabled: true                                    # 是否启用音效
  buy-success:
    sound: minecraft:entity.experience_orb.pickup  # 购买成功音效
    volume: 1.0
    pitch: 1.2
  buy-fail:
    sound: minecraft:entity.villager.no            # 购买失败音效
    volume: 1.0
    pitch: 1.0
  sell-success:
    sound: minecraft:block.note_block.bell         # 出售成功音效
    volume: 1.0
    pitch: 1.0
  sell-fail:
    sound: minecraft:entity.villager.no            # 出售失败音效
    volume: 1.0
    pitch: 1.0
  click:
    sound: minecraft:ui.button.click               # 界面点击音效
    volume: 0.5
    pitch: 1.0

# GUI图标设置
# 格式: minecraft:item_name 或 modid:item_name
# 也支持旧格式: MATERIAL_NAME (如 EMERALD)
gui-icons:
  # 主菜单
  main-menu:
    buy: minecraft:emerald              # 购买按钮图标
    sell: minecraft:gold_ingot          # 出售按钮图标
    info: minecraft:book                # 信息按钮图标
  # 购买界面
  buy-gui:
    all-category: minecraft:nether_star # 全部分类按钮
    category-page: minecraft:book       # 分类翻页按钮
    balance: minecraft:gold_nugget      # 余额显示图标
    switch-sell: minecraft:gold_ingot   # 切换出售按钮
    prev-page: minecraft:arrow          # 上一页按钮
    next-page: minecraft:arrow          # 下一页按钮
    close: minecraft:barrier            # 关闭按钮
    divider: minecraft:black_stained_glass_pane  # 分割栏
    filler: minecraft:gray_stained_glass_pane    # 填充玻璃
  # 出售界面
  sell-gui:
    confirm: minecraft:emerald_block    # 确认出售按钮
    back: minecraft:barrier             # 返回按钮
    filler: minecraft:gray_stained_glass_pane    # 填充玻璃

可用变量 (PlaceholderAPI)

背包相关


变量说明
%muudm_inventory_value%背包物品总价值 (扣税后,中文单位)
%muudm_inventory_value_raw%背包物品总价值 (扣税后,原始数字)
%muudm_inventory_value_notax%背包物品总价值 (不含税,中文单位)
%muudm_inventory_value_notax_raw%背包物品总价值 (不含税,原始数字)
%muudm_inventory_count%背包中可出售物品数量
%muudm_inventory_types%背包中可出售物品种类数

保险箱相关 (需安装 WarZSafeBox) https://www.minebbs.com/resources/warzsafebox-mc.11399/


变量说明
%muudm_safebox_value%保险箱物品总价值 (不含税,中文单位)
%muudm_safebox_value_raw%保险箱物品总价值 (不含税,原始数字)
%muudm_safebox_value_tax%保险箱物品总价值 (扣税后,中文单位)
%muudm_safebox_value_tax_raw%保险箱物品总价值 (扣税后,原始数字)

总价值 (背包 + 保险箱)


变量说明
%muudm_total_value%总价值 (不含税,中文单位)
%muudm_total_value_raw%总价值 (不含税,原始数字)
%muudm_total_value_tax%总价值 (扣税后,中文单位)
%muudm_total_value_tax_raw%总价值 (扣税后,原始数字)
提供的API大佬们来制作附属包!!!

MuuDm-Q—— 市场交易排行榜/趋势分析 附属插件

代码:
#### Maven
```xml
<repositories>
    <repository>
        <id>local-repo</id>
        <url>file://${project.basedir}/libs</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>com.muumuui.muudm</groupId>
        <artifactId>MuuDm</artifactId>
        <version>1.0.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
```
#### Gradle
```groovy
dependencies {
    compileOnly files('libs/MuuDm.jar')
}
```
### plugin.yml配置
```yaml
depend: [MuuDm]
# 或软依赖
softdepend: [MuuDm]
```
### 基本使用
```java
import com.muumuuimuuDm.api.MuuDmAPI;
public class MyPlugin extends JavaPlugin {
    private MuuDmAPI marketAPI;
    @Override
    public void onEnable() {
        // 检查MuuDm是否已加载
        if (!MuuDmAPI.isInitialized()) {
            getLogger().severe("MuuDm未安装或未启动!");
            getServer().getPluginManager().disablePlugin(this);
            return;
        }
        // 获取API实例
        marketAPI = MuuDmAPI.getInstance();
        // 使用API
        getLogger().info("市场中有 " + marketAPI.getTotalItemCount() + " 个物品");
    }
}
```
---
## 核心API
### MuuDmAPI 类
#### 获取API实例
```java
MuuDmAPI api = MuuDmAPI.getInstance();
```
#### 物品查询
```java
// 根据ID获取物品
MarketItem item = api.getItemById(1);
// 获取所有物品
Collection<MarketItem> allItems = api.getAllItems();
// 获取可购买的物品
List<MarketItem> purchasable = api.getPurchasableItems();
// 根据分类获取物品
List<MarketItem> items = api.getItemsByCategory("矿物");
// 通过ItemStack查找相似物品
ItemStack diamond = new ItemStack(Material.DIAMOND);
MarketItem marketDiamond = api.findSimilarItem(diamond);
```
#### 价格管理
```java
// 设置物品价格
api.setItemPrice(item, 100.0);
// 按百分比调整价格(+5%)
api.adjustItemPrice(item, 5.0);
// 调整所有物品价格(-10%)
api.adjustAllPrices(-10.0);
// 重置所有价格为原价
api.resetAllPrices();
```
#### 库存管理
```java
// 设置库存
api.setItemStock(item, 1000);
// 设置每日补货量
api.setItemDailyRestock(item, 100);
// 设置最大库存
api.setItemMaxStock(item, 5000);
// 设置单次最大购买量
api.setItemMaxBuyAmount(item, 64);
// 手动补充所有库存
api.restockAll();
```
#### 分类管理
```java
// 获取所有分类
Set<String> categories = api.getCategories();
// 创建新分类
ItemStack icon = new ItemStack(Material.DIAMOND_BLOCK);
api.createCategory("珍稀物品", icon);
// 删除分类
api.removeCategory("珍稀物品");
// 获取分类中的物品数量
int count = api.getItemCountByCategory("矿物");
```
#### 物品管理
```java
// 添加物品到市场
ItemStack item = new ItemStack(Material.DIAMOND);
api.addItem(
    item,           // 物品
    "矿物",         // 分类
    100.0,          // 价格
    10,             // 权重
    50,             // 每日补货
    true            // 是否可购买
);
// 移除物品
api.removeItem(marketItem);
// 重新加载所有物品
api.loadItems();
```
#### 统计查询
```java
// 获取市场总物品数
int total = api.getTotalItemCount();
// 获取市场总价值
double value = api.getTotalMarketValue();
// 获取最贵的10个物品
List<MarketItem> expensive = api.getMostExpensiveItems(10);
// 获取最便宜的10个物品
List<MarketItem> cheap = api.getCheapestItems(10);
// 获取库存最少的10个物品
List<MarketItem> lowStock = api.getLowestStockItems(10);
// 获取涨幅最大的10个物品
List<MarketItem> inflated = api.getMostInflatedItems(10);
// 获取跌幅最大的10个物品
List<MarketItem> deflated = api.getMostDeflatedItems(10);
```
#### 异步API
```java
// 异步获取所有物品
api.getAllItemsAsync().thenAccept(items -> {
    // 在主线程中执行
    Bukkit.getScheduler().runTask(plugin, () -> {
        getLogger().info("加载了 " + items.size() + " 个物品");
    });
});
// 异步获取物品价格历史
api.getItemPriceHistoryAsync(1, 7).thenAccept(history -> {
    double currentPrice = (double) history.get("currentPrice");
    getLogger().info("当前价格: " + currentPrice);
});
// 异步批量调整价格
api.adjustAllPricesAsync(5.0).thenAccept(count -> {
    getLogger().info("调整了 " + count + " 个物品的价格");
});
```
---
## 事件系统
### 可用事件
#### MarketBuyEvent
玩家购买物品时触发
```java
@EventHandler
public void onMarketBuy(MarketBuyEvent event) {
    Player player = event.getPlayer();
    MarketItem item = event.getItem();
    int amount = event.getAmount();
    double totalPrice = event.getTotalPrice();
    double priceChange = event.getPriceChange();
    player.sendMessage("你购买了 " + amount + " 个物品");
    player.sendMessage("价格上涨了 " + priceChange);
    // 取消购买
    if (player.getLevel() < 10) {
        event.setCancelled(true);
        player.sendMessage("等级不足10级,无法购买!");
    }
}
```
#### MarketSellEvent
玩家出售物品时触发
```java
@EventHandler
public void onMarketSell(MarketSellEvent event) {
    Player player = event.getPlayer();
    MarketItem item = event.getItem();
    int amount = event.getAmount();
    double totalPrice = event.getTotalPrice();
    player.sendMessage("你出售了 " + amount + " 个物品,获得 " + totalPrice);
    // 取消出售
    if (item.getStock() > 10000) {
        event.setCancelled(true);
        player.sendMessage("该物品库存已满,暂时无法出售!");
    }
}
```
#### MarketPriceChangeEvent
物品价格变化时触发
```java
@EventHandler
public void onPriceChange(MarketPriceChangeEvent event) {
    MarketItem item = event.getItem();
    double oldPrice = event.getOldPrice();
    double newPrice = event.getNewPrice();
    PriceChangeReason reason = event.getReason();
    // 阻止价格下跌
    if (newPrice < oldPrice) {
        event.setCancelled(true);
        return;
    }
    // 修改价格
    if (newPrice > oldPrice * 2) {
        event.setNewPrice(oldPrice * 2); // 最多涨到2倍
    }
    // 根据原因执行不同操作
    switch (reason) {
        case BUY:
            // 玩家购买导致涨价
            break;
        case SELL:
            // 玩家出售导致降价
            break;
        case DAILY_INCREASE:
            // 每日自动涨价
            break;
        case ADMIN_ADJUST:
            // 管理员手动调整
            break;
    }
}
```
#### MarketItemAddEvent
物品被添加到市场时触发
```java
@EventHandler
public void onItemAdd(MarketItemAddEvent event) {
    MarketItem item = event.getItem();
    CommandSender adder = event.getAdder();
    // 阻止添加某些物品
    if (item.getItem().getType() == Material.BEDROCK) {
        event.setCancelled(true);
        adder.sendMessage("不能添加基岩到市场!");
    }
}
```
#### MarketItemRemoveEvent
物品从市场移除时触发
```java
@EventHandler
public void onItemRemove(MarketItemRemoveEvent event) {
    MarketItem item = event.getItem();
    CommandSender remover = event.getRemover();
    // 记录日志
    plugin.getLogger().info(remover.getName() + " 移除了物品: " + item.getId());
}
```
#### MarketRestockEvent
市场执行每日补货时触发
```java
@EventHandler
public void onRestock(MarketRestockEvent event) {
    int count = event.getRestockedItems();
    Bukkit.broadcastMessage("市场已补货 " + count + " 个物品!");
}
```
---
## 回调系统
### PreTradeCallback
交易前回调,可以阻止交易
```java
MuuDmAPI api = MuuDmAPI.getInstance();
api.registerPreTradeCallback((player, item, amount, isBuying) -> {
    // 检查玩家等级
    if (player.getLevel() < 10) {
        player.sendMessage("等级不足10级,无法交易!");
        return false; // 阻止交易
    }
    // 检查物品类型
    if (item.getItem().getType() == Material.DIAMOND && isBuying) {
        if (amount > 10) {
            player.sendMessage("钻石每次最多只能购买10个!");
            return false;
        }
    }
    return true; // 允许交易
});
```
### PostTradeCallback
交易后回调
```java
api.registerPostTradeCallback((player, item, amount, totalPrice, isBuying) -> {
    // 交易后奖励积分
    if (isBuying) {
        // 购买后给予积分
        givePoints(player, amount);
    } else {
        // 出售后给予额外奖励
        if (totalPrice > 1000) {
            player.sendMessage("大额交易奖励!获得额外100金币");
            api.getEconomy().depositPlayer(player, 100);
        }
    }
    // 统计玩家交易次数
    incrementTradeCount(player);
});
```
### PriceCalculationCallback
自定义价格计算
```java
api.setPriceCalculationCallback((item, currentPrice, amount, isBuying) -> {
    // 自定义价格计算逻辑
    // 例如:根据交易量动态调整涨跌幅
    double baseRate = isBuying ? 0.001 : 0.002;
    double multiplier = Math.log(amount + 1) / Math.log(2); // 对数缩放
    double rate = baseRate * multiplier;
    double newPrice;
    if (isBuying) {
        newPrice = currentPrice * (1 + rate);
    } else {
        newPrice = currentPrice * (1 - rate);
    }
    // 限制价格范围
    double minPrice = item.getOriginalPrice() * 0.5;
    double maxPrice = item.getOriginalPrice() * 2.0;
    return Math.max(minPrice, Math.min(maxPrice, newPrice));
});
```
### RestockCallback
自定义补货逻辑
```java
api.setRestockCallback((item, currentStock, defaultRestock) -> {
    // 根据当前库存动态调整补货量
    int maxStock = item.getMaxStock() > 0 ? item.getMaxStock() : 1000;
    if (currentStock < maxStock * 0.2) {
        // 库存低于20%,双倍补货
        return defaultRestock * 2;
    } else if (currentStock > maxStock * 0.8) {
        // 库存高于80%,减半补货
        return defaultRestock / 2;
    }
    return defaultRestock;
});
```
---
## Hook框架
### 创建自定义Hook
```java
import com.muumuuimuuDm.api.hook.PluginHook;
public class MyPluginHook extends PluginHook {
    private Method someMethod;
    public MyPluginHook(Logger logger) {
        super("TargetPluginName", logger);
    }
    @Override
    protected boolean onHook() {
        try {
            // 获取目标插件的类
            Class<?> targetClass = getClass("com.example.targetplugin.TargetClass");
            if (targetClass == null) return false;
            // 获取方法
            someMethod = getMethod(targetClass, "someMethod", Player.class);
            return true;
        } catch (Exception e) {
            logger.warning("Hook失败: " + e.getMessage());
            return false;
        }
    }
    // 提供公开方法供外部调用
    public Object callSomeMethod(Player player) {
        if (!isEnabled()) return null;
        try {
            Object instance = hookedPlugin; // 或其他实例
            return invokeMethod(instance, someMethod, player);
        } catch (Exception e) {
            return null;
        }
    }
}
```
### 使用Hook管理器
```java
import com.muumuuimuuDm.api.hook.HookManager;
// 在插件主类中
HookManager hookManager = new HookManager(this);
// 注册Hook
MyPluginHook myHook = new MyPluginHook(getLogger());
hookManager.registerHook(myHook);
// 使用Hook
if (hookManager.isHookEnabled("TargetPluginName")) {
    Optional<MyPluginHook> hook = hookManager.getHook("TargetPluginName", MyPluginHook.class);
    hook.ifPresent(h -> {
        Object result = h.callSomeMethod(player);
    });
}
// 注销时清理
@Override
public void onDisable() {
    hookManager.unregisterAll();
}
```
### 内置Hook
#### CitizensHook
```java
import com.muumuuimuuDm.api.hook.CitizensHook;
CitizensHook citizens = new CitizensHook(getLogger());
if (citizens.isEnabled()) {
    // 检查实体是否为NPC
    if (citizens.isNPC(entity)) {
        // 处理NPC交互
    }
}
```
#### PlayerPointsHook
```java
import com.muumuuimuuDm.api.hook.PlayerPointsHook;
PlayerPointsHook points = new PlayerPointsHook(getLogger());
if (points.isEnabled()) {
    // 获取玩家点券
    int balance = points.getPoints(player);
    // 扣除点券
    if (points.takePoints(player, 100)) {
        player.sendMessage("消费100点券");
    }
}
```
#### EssentialsHook
```java
import com.muumuuimuuDm.api.hook.EssentialsHook;
EssentialsHook ess = new EssentialsHook(getLogger());
if (ess.isEnabled()) {
    // 检查玩家是否AFK
    if (ess.isAfk(player)) {
        player.sendMessage("你现在是AFK状态,无法交易");
        return;
    }
}
```
---
## 数据统计API
### MarketDataAPI 类
```java
import com.muumuuimuuDm.api.data.MarketDataAPI;
MarketDataAPI dataAPI = new MarketDataAPI(MuuDm.getInstance());
```
### 交易记录查询
```java
// 获取玩家的交易记录
List<TradeRecord> records = dataAPI.getPlayerTrades(player.getUniqueId().toString(), 50);
for (TradeRecord record : records) {
    System.out.println(record.playerName + " " +
                      record.tradeType + " " +
                      record.amount + "个物品 " +
                      "价格: " + record.price);
}
// 异步获取
dataAPI.getPlayerTradesAsync(uuid, 50).thenAccept(records -> {
    // 处理记录
});
// 获取物品的交易记录
List<TradeRecord> itemTrades = dataAPI.getItemTrades(itemId, 100);
// 获取最近的交易
List<TradeRecord> recentTrades = dataAPI.getRecentTrades(20);
```
### 玩家统计
```java
// 获取玩家统计
PlayerStats stats = dataAPI.getPlayerStats(player.getUniqueId().toString());
if (stats != null) {
    player.sendMessage("总交易次数: " + stats.totalTrades);
    player.sendMessage("总消费: " + stats.totalSpent);
    player.sendMessage("总收入: " + stats.totalEarned);
    player.sendMessage("总税收: " + stats.totalTax);
}
```
### 排行榜
```java
// 消费排行榜(前10名)
List<PlayerStats> topSpenders = dataAPI.getTopSpenders(10);
for (int i = 0; i < topSpenders.size(); i++) {
    PlayerStats stats = topSpenders.get(i);
    System.out.println((i + 1) + ". " + stats.playerName +
                      " 消费: " + stats.totalSpent);
}
// 收入排行榜
List<PlayerStats> topSellers = dataAPI.getTopSellers(10);
// 交易次数排行榜
List<PlayerStats> topTraders = dataAPI.getTopTraders(10);
```
### 物品统计
```java
// 获取物品统计
ItemStats itemStats = dataAPI.getItemStats(itemId);
if (itemStats != null) {
    System.out.println("总购买量: " + itemStats.totalBought);
    System.out.println("总出售量: " + itemStats.totalSold);
    System.out.println("总收益: " + itemStats.totalRevenue);
}
// 获取热门商品
List<ItemStats> hotItems = dataAPI.getHotItems(10);
```
### 服务器统计
```java
// 总交易次数
int totalTrades = dataAPI.getTotalTradeCount();
// 总交易额
double totalVolume = dataAPI.getTotalTradeVolume();
// 总税收
double totalTax = dataAPI.getTotalTaxCollected();
System.out.println("市场总交易次数: " + totalTrades);
System.out.println("市场总交易额: " + totalVolume);
System.out.println("市场总税收: " + totalTax);
```
---
## GUI扩展
### 创建自定义GUI
#### 方法1: 实现CustomGUI接口
```java
import com.muumuuimuuDm.api.gui.CustomGUI;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public class MyMarketGUI implements CustomGUI {
    private Inventory inventory;
    @Override
    public String getIdentifier() {
        return "my_custom_market";
    }
    @Override
    public String getTitle() {
        return "§6我的自定义市场";
    }
    @Override
    public int getSize() {
        return 54; // 6行
    }
    @Override
    public void open(Player player) {
        inventory = Bukkit.createInventory(null, getSize(), getTitle());
        // 设置GUI内容
        setupInventory(player);
        player.openInventory(inventory);
    }
    @Override
    public boolean handleClick(Player player, int slot, boolean isShiftClick, boolean isRightClick) {
        // 处理点击事件
        // 返回true取消事件,false允许事件
        if (slot == 0) {
            player.sendMessage("你点击了第一个槽位!");
            return true; // 取消事件
        }
        return true;
    }
    @Override
    public Inventory getInventory() {
        return inventory;
    }
    private void setupInventory(Player player) {
        // 设置物品
        // ...
    }
}
```
#### 方法2: 继承AbstractCustomGUI
```java
import com.muumuuimuuDm.api.gui.AbstractCustomGUI;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class SimpleGUI extends AbstractCustomGUI {
    public SimpleGUI() {
        super("simple_gui", "§a简单GUI", 27); // 3行
    }
    @Override
    protected void setupGUI(Player player) {
        // 设置GUI内容
        inventory.setItem(13, new ItemStack(Material.DIAMOND));
    }
    @Override
    public boolean handleClick(Player player, int slot, boolean isShiftClick, boolean isRightClick) {
        if (slot == 13) {
            player.sendMessage("你点击了钻石!");
        }
        return true;
    }
}
```
### 注册和使用GUI
```java
import com.muumuuimuuDm.api.gui.GUIRegistry;
// 注册GUI
MyMarketGUI gui = new MyMarketGUI();
GUIRegistry.register(gui);
// 打开GUI
GUIRegistry.openGUI("my_custom_market", player);
// 检查GUI是否已注册
if (GUIRegistry.isRegistered("my_custom_market")) {
    // ...
}
// 获取GUI实例
Optional<CustomGUI> optionalGUI = GUIRegistry.getGUI("my_custom_market");
optionalGUI.ifPresent(g -> g.open(player));
// 注销GUI
GUIRegistry.unregister("my_custom_market");
```
### GUI点击处理
需要在GUIListener中处理自定义GUI的点击:
```java
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
    if (event.getInventory().getHolder() instanceof CustomGUI) {
        CustomGUI gui = (CustomGUI) event.getInventory().getHolder();
        event.setCancelled(true);
        Player player = (Player) event.getWhoClicked();
        int slot = event.getRawSlot();
        boolean shift = event.getClick().isShiftClick();
        boolean right = event.getClick().isRightClick();
        gui.handleClick(player, slot, shift, right);
    }
}
```
---
## PlaceholderAPI变量
### 背包物品价值
| 变量 | 说明 |
|------|------|
| `%muudm_inventory_value%` | 背包物品总价值(扣税后,中文单位) |
| `%muudm_inventory_value_raw%` | 背包物品总价值(扣税后,原始数字) |
| `%muudm_inventory_value_notax%` | 背包物品总价值(不含税,中文单位) |
| `%muudm_inventory_value_notax_raw%` | 背包物品总价值(不含税,原始数字) |
| `%muudm_inventory_count%` | 背包可出售物品数量 |
| `%muudm_inventory_types%` | 背包可出售物品种类数 |
### 保险箱物品价值
| 变量 | 说明 |
|------|------|
| `%muudm_safebox_value%` | 保险箱物品总价值(不含税,中文单位) |
| `%muudm_safebox_value_raw%` | 保险箱物品总价值(不含税,原始数字) |
| `%muudm_safebox_value_tax%` | 保险箱物品总价值(扣税后,中文单位) |
| `%muudm_safebox_value_tax_raw%` | 保险箱物品总价值(扣税后,原始数字) |
### 总价值
| 变量 | 说明 |
|------|------|
| `%muudm_total_value%` | 总价值(背包+保险箱,不含税,中文单位) |
| `%muudm_total_value_raw%` | 总价值(背包+保险箱,不含税,原始数字) |
| `%muudm_total_value_tax%` | 总价值(背包+保险箱,扣税后,中文单位) |
| `%muudm_total_value_tax_raw%` | 总价值(背包+保险箱,扣税后,原始数字) |
### 物品信息(支持动态ID)
| 变量格式 | 说明 | 示例 |
|---------|------|------|
| `%muudm_item_price_<id>%` | 物品当前价格 | `%muudm_item_price_1%` |
| `%muudm_item_stock_<id>%` | 物品库存 | `%muudm_item_stock_1%` |
| `%muudm_item_name_<id>%` | 物品名称 | `%muudm_item_name_1%` |
### 市场信息
| 变量 | 说明 |
|------|------|
| `%muudm_market_items%` | 市场物品总数 |
| `%muudm_market_categories%` | 市场分类总数 |
| `%muudm_market_value%` | 市场总价值(中文单位) |
| `%muudm_market_value_raw%` | 市场总价值(原始数字) |
### 玩家信息
| 变量 | 说明 |
|------|------|
| `%muudm_balance%` | 玩家余额(中文单位) |
| `%muudm_balance_raw%` | 玩家余额(原始数字) |
### 配置信息
| 变量 | 说明 |
|------|------|
| `%muudm_tax_buy%` | 购买税率(百分比) |
| `%muudm_tax_sell%` | 出售税率(百分比) |
---
## 完整示例
### 示例1: 创建市场扩展插件
```java
package com.example.marketaddon;
import com.muumuuimuuDm.api.MuuDmAPI;
import com.muumuuimuuDm.event.MarketBuyEvent;
import com.muumuuimuuDm.model.MarketItem;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
public class MarketAddon extends JavaPlugin implements Listener {
    private MuuDmAPI api;
    @Override
    public void onEnable() {
        // 检查MuuDm
        if (!MuuDmAPI.isInitialized()) {
            getLogger().severe("MuuDm未安装!");
            getServer().getPluginManager().disablePlugin(this);
            return;
        }
        api = MuuDmAPI.getInstance();
        getServer().getPluginManager().registerEvents(this, this);
        // 注册交易前回调
        api.registerPreTradeCallback(this::onPreTrade);
        // 注册交易后回调
        api.registerPostTradeCallback(this::onPostTrade);
        getLogger().info("市场扩展插件已启用!");
    }
    private boolean onPreTrade(Player player, MarketItem item, int amount, boolean isBuying) {
        // VIP玩家免税
        if (player.hasPermission("addon.vip")) {
            player.sendMessage("§aVIP免税优惠!");
            return true;
        }
        // 限制购买数量
        if (isBuying && amount > 64) {
            player.sendMessage("§c单次最多只能购买64个!");
            return false;
        }
        return true;
    }
    private void onPostTrade(Player player, MarketItem item, int amount, double totalPrice, boolean isBuying) {
        // 大额交易奖励
        if (totalPrice > 10000) {
            player.sendMessage("§6§l大额交易奖励!§e获得100积分");
            // 给予积分...
        }
    }
    @EventHandler
    public void onMarketBuy(MarketBuyEvent event) {
        Player player = event.getPlayer();
        // 显示价格变化
        double change = event.getPriceChangePercent();
        player.sendMessage(String.format("§e价格上涨了 §c%.2f%%", change));
    }
}
```
### 示例2: 自定义价格算法
```java
package com.example.pricecontroller;
import com.muumuuimuuDm.api.MuuDmAPI;
import org.bukkit.plugin.java.JavaPlugin;
public class PriceController extends JavaPlugin {
    @Override
    public void onEnable() {
        MuuDmAPI api = MuuDmAPI.getInstance();
        // 设置自定义价格计算
        api.setPriceCalculationCallback((item, currentPrice, amount, isBuying) -> {
            // 基于供需的非线性价格模型
            double elasticity = 0.5; // 价格弹性系数
            double stockRatio = (double) item.getStock() / item.getMaxStock();
            // 库存越少,价格变化越大
            double impact = elasticity * (1 - stockRatio);
            double newPrice;
            if (isBuying) {
                // 购买:库存减少,价格上涨
                double rate = 0.001 * (1 + impact);
                newPrice = currentPrice * (1 + rate * amount);
            } else {
                // 出售:库存增加,价格下跌
                double rate = 0.002 * (1 + impact);
                newPrice = currentPrice * (1 - rate * amount);
            }
            // 限制价格范围
            double minPrice = item.getOriginalPrice() * 0.3;
            double maxPrice = item.getOriginalPrice() * 3.0;
            return Math.max(minPrice, Math.min(maxPrice, newPrice));
        });
        getLogger().info("自定义价格算法已启用!");
    }
}
```
### 示例3: 市场统计看板
```java
package com.example.marketstats;
import com.muumuuimuuDm.api.MuuDmAPI;
import com.muumuuimuuDm.api.data.MarketDataAPI;
import com.muumuuimuuDm.api.data.MarketDataAPI.PlayerStats;
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.List;
public class MarketStats extends JavaPlugin {
    private MarketDataAPI dataAPI;
    @Override
    public void onEnable() {
        dataAPI = new MarketDataAPI(com.muumuuimuuDm.MuuDm.getInstance());
    }
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (command.getName().equalsIgnoreCase("marketstats")) {
            if (sender instanceof Player) {
                showStats((Player) sender);
            }
            return true;
        }
        return false;
    }
    private void showStats(Player player) {
        player.sendMessage("§6§l=== 市场统计 ===");
        // 服务器统计
        int totalTrades = dataAPI.getTotalTradeCount();
        double totalVolume = dataAPI.getTotalTradeVolume();
        double totalTax = dataAPI.getTotalTaxCollected();
        player.sendMessage("§e总交易次数: §f" + totalTrades);
        player.sendMessage("§e总交易额: §f" + String.format("%.2f", totalVolume));
        player.sendMessage("§e总税收: §f" + String.format("%.2f", totalTax));
        player.sendMessage("");
        player.sendMessage("§6§l=== 消费排行榜 TOP 5 ===");
        // 消费排行榜
        List<PlayerStats> topSpenders = dataAPI.getTopSpenders(5);
        for (int i = 0; i < topSpenders.size(); i++) {
            PlayerStats stats = topSpenders.get(i);
            player.sendMessage(String.format("§e%d. §f%s §7- §6%.2f",
                i + 1, stats.playerName, stats.totalSpent));
        }
        // 个人统计
        player.sendMessage("");
        player.sendMessage("§6§l=== 你的统计 ===");
        PlayerStats myStats = dataAPI.getPlayerStats(player.getUniqueId().toString());
        if (myStats != null) {
            player.sendMessage("§e交易次数: §f" + myStats.totalTrades);
            player.sendMessage("§e总消费: §c" + String.format("%.2f", myStats.totalSpent));
            player.sendMessage("§e总收入: §a" + String.format("%.2f", myStats.totalEarned));
            player.sendMessage("§e总税收: §7" + String.format("%.2f", myStats.totalTax));
        } else {
            player.sendMessage("§7还没有交易记录");
        }
    }
}
```
### 示例4: 自定义GUI
```java
package com.example.customgui;
import com.muumuuimuuDm.api.MuuDmAPI;
import com.muumuuimuuDm.api.gui.AbstractCustomGUI;
import com.muumuuimuuDm.api.gui.GUIRegistry;
import com.muumuuimuuDm.model.MarketItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Arrays;
import java.util.List;
public class CustomGUIPlugin extends JavaPlugin {
    @Override
    public void onEnable() {
        // 注册自定义GUI
        GUIRegistry.register(new HotItemsGUI());
    }
    // 热门商品GUI
    static class HotItemsGUI extends AbstractCustomGUI {
        public HotItemsGUI() {
            super("hot_items", "§c§l热门商品", 54);
        }
        @Override
        protected void setupGUI(Player player) {
            MuuDmAPI api = MuuDmAPI.getInstance();
            // 获取最贵的物品
            List<MarketItem> expensive = api.getMostExpensiveItems(9);
            for (int i = 0; i < Math.min(expensive.size(), 9); i++) {
                MarketItem item = expensive.get(i);
                ItemStack display = item.getItem().clone();
                ItemMeta meta = display.getItemMeta();
                if (meta != null) {
                    meta.setDisplayName("§6" + item.getItem().getType().toString());
                    meta.setLore(Arrays.asList(
                        "§e价格: §f" + String.format("%.2f", item.getCurrentPrice()),
                        "§e库存: §f" + item.getStock(),
                        "§a左键购买 1个",
                        "§aShift+左键购买 64个"
                    ));
                    display.setItemMeta(meta);
                }
                inventory.setItem(i, display);
            }
            // 添加关闭按钮
            ItemStack close = new ItemStack(Material.BARRIER);
            ItemMeta closeMeta = close.getItemMeta();
            if (closeMeta != null) {
                closeMeta.setDisplayName("§c关闭");
                close.setItemMeta(closeMeta);
            }
            inventory.setItem(49, close);
        }
        @Override
        public boolean handleClick(Player player, int slot, boolean isShiftClick, boolean isRightClick) {
            if (slot == 49) {
                player.closeInventory();
                return true;
            }
            if (slot < 9) {
                MuuDmAPI api = MuuDmAPI.getInstance();
                List<MarketItem> expensive = api.getMostExpensiveItems(9);
                if (slot < expensive.size()) {
                    MarketItem item = expensive.get(slot);
                    int amount = isShiftClick ? 64 : 1;
                    // 尝试购买
                    if (api.buyItem(item.getId(), amount)) {
                        player.sendMessage("§a购买成功!");
                        reload(player); // 刷新GUI
                    } else {
                        player.sendMessage("§c购买失败!");
                    }
                }
            }
            return true;
        }
    }
}
```
---
## 结语
MuuDm API提供了丰富的扩展功能,让你能够:
- ✅ 监听和控制市场交易事件
- ✅ 自定义价格计算和补货逻辑
- ✅ 集成其他插件功能
- ✅ 创建自定义GUI界面
- ✅ 查询详细的交易统计数据
- ✅ 使用PlaceholderAPI变量
如有问题或建议,欢迎反馈!
  • 1768313234765.webp
    1768313234765.webp
    99.2 KB · 查看: 12
作者
木Mu
查看
328
首次发布
最后更新

评分

0.00 星 0 次评分

木Mu 的其他资源

后退
顶部 底部