🛒 AdventureShop

一、简介

AdventureShop —— 一款全随机商品商店系统,冒险商城

AdventureShop 允许您创建全随机刷新的商品商店。每个商品拥有稀有度等级,价格随机浮动,让玩家每次打开商店都有不同的购物体验。支持8种商店类型、6级稀有度、三层定价、三层折扣、多货币支付和邮件发放。

AdventureShop 支持 Paper / Spigot 1.21.4+ 服务器(Java 21),并且会第一时间支持未来版本。

AdventureShop

  • 8种商店类型 > 日/周/月/永久 × 出售/收购
  • 6级稀有度 > 权重随机抽取,价格系数联动
  • 三层定价 > 基础价 × 稀有度系数 × 随机浮动
  • 多货币 > Vault / PlayerPoints / 物品货币
  • 三层折扣 > 全局 / 商店级 / 商品级,叠加可控
  • 4种发放通道 > 背包/邮件 7/30/180 天
  • 商品池 > 支持海量商品随机抽取上架
  • GUI商店 > 全GUI交互,美观易用
  • 数据存储 > 支持 SQLite 本地存储
  • 高自定义 > 商品配置、GUI布局、消息文本全部YAML可配

二、插件前置说明

都是非必须(除 AdventureLib)

  • AdventureLib — 必需前置库
  • Vault — 经济插件(需基础插件例如ess,cmi等)
  • PlayerPoints — 点券插件
  • PlaceholderAPI — PAPI变量支持
  • AdventureManage — 经济联动
  • AdventureMail — 邮件系统,背包满时自动邮寄

📥 安装与目录

环境要求

项目要求
服务端Spigot / Paper 1.21.4+
Java21+
必需依赖AdventureLib
可选依赖Vault、PlayerPoints、AdventureManage、AdventureMail、PlaceholderAPI

安装步骤

  1. 放入 AdventureLib.jar + AdventureShop-1.2.2.jar
  2. 按需安装 Vault / AdventureManage / AdventureMail
  3. 启动服务器自动生成配置
  4. 编辑 config.ymlitems/*.yml
  5. /ashopadmin reload

目录结构

plugins/AdventureShop/
  config.yml          # 主配置
  messages.yml        # 消息文本
  gui.yml             # GUI 布局
  items/
    weapons.yml       # 武器物品池
    blocks.yml        # 建材物品池
    misc.yml          # 杂货物品池
  Translations/
    items_CN.yml      # 物品名中文翻译
  data/
    adventureshop.db  # SQLite 数据库

🏪 商店类型

商店由刷新周期交易方向两个维度组合,共 8 种:

类型配置键周期方向说明
今日热销daySell每日出售每天自动刷新
本周热销weekSell每周出售每周一刷新
本月热销monthSell每月出售每月1号刷新
固定出售onlySell永久出售不自动刷新
今日收购dayBuy每日收购玩家出售给商店
本周收购weekBuy每周收购每周一刷新
本月收购monthBuy每月收购每月1号刷新
固定收购onlyBuy永久收购不自动刷新
ℹ️ 提示

出售商店:玩家花钱 → 商店给物品
收购商店:玩家交物品 → 商店给钱(收购价 = 出售价 × buy-back-ratio,默认 0.5)

稀有度系统

每件物品必须指定稀有度,影响抽取概率价格系数

等级显示名默认权重价格系数
NORMAL普通 (白)0.80×1.0
ADVANCED高级 (蓝)0.50×1.2
RARE稀有 (紫)0.30×1.5
RARER罕见 (粉)0.20×2.0
EPIC史诗 (黄)0.10×3.0
MYTHICAL神话 (金)0.01×5.0

权重覆盖

daySell-weapon:
  rarity-weights:
    normal: 5        # 权重越高越容易出现
    advanced: 3
    rare: 2
    mythical: 0      # 0 = 不出现

📦 物品池

物品池位于 items/ 目录,一个 YAML 文件 = 一个类别。

字段说明

字段类型说明
materialMaterialBukkit 物品材质
categoryString所属类别(匹配商店 category)
rarityRarity稀有度等级
base-pricedouble基础价格
price-variancedouble浮动比例 (0.15 = ±15%)
currencyString货币 ID
global-stockint全服库存 (0=不限)
player-limitint每人限购 (0=不限)
deliveryChannel发放通道
discountSectionC 层商品折扣 (可选)

示例

# items/weapons.yml
iron_sword:
  material: IRON_SWORD
  category: weapon
  rarity: normal
  base-price: 50
  price-variance: 0.15
  currency: vault
  global-stock: 10
  player-limit: 2
  delivery: INVENTORY

diamond_sword:
  material: DIAMOND_SWORD
  category: weapon
  rarity: rare
  base-price: 500
  price-variance: 0.2
  currency: vault
  global-stock: 3
  player-limit: 1
  delivery: INVENTORY
  discount:
    enabled: true
    rate: 0.85
    permission: "adventureshop.discount.weapon"

mace:
  material: MACE
  category: weapon
  rarity: mythical
  base-price: 10000
  currency: gem
  global-stock: 1
  delivery: MAIL_180D
⚠️ 注意

物品 category 必须与商店定义的 category 匹配。default 类别会从所有物品中抽取。

💲 定价与刷新

三层定价引擎

公式

最终价格 = 基础价 × 稀有度系数 × (1 ± 随机浮动)

例:钻石剑 base-price=500, RARE (×1.5), variance=0.2

最低 = 500 × 1.5 × 0.8 = 600
最高 = 500 × 1.5 × 1.2 = 900
收购价 = 出售价 × buy-back-ratio (默认 0.5)

自动刷新

周期刷新时间配置
每日daily-timerefresh.daily-time: "00:00"
每周weekly-dayrefresh.weekly-day: "MONDAY"
每月monthly-dayrefresh.monthly-day: 1
永久不自动刷新

玩家手动刷新

第 N 次费用 = base-cost × cost-increase ^ (N-1)

示例 (base=500, increase=1.5):
第1次: 500 / 第2次: 750 / 第3次: 1125
配置默认说明
cost-typevault费用货币
base-cost500首次费用
cost-increase1.5递增倍率
max-per-day3每日上限
ℹ️ 权限覆盖

adventureshop.refresh.N 覆盖每日上限。如 adventureshop.refresh.5 = 每天 5 次。

📬 物品发放

通道说明
背包直发INVENTORY放入背包,满了走兜底
邮件 7 天MAIL_7DAdventureMail 7 天
邮件 30 天MAIL_30DAdventureMail 30 天
邮件 180 天MAIL_180DAdventureMail 180 天

兜底机制

INVENTORY 通道降级链:

  1. 放入背包
  2. 背包满 → 检查 AdventureMail
  3. AM 可用 → 发邮箱 (默认 3 天)
  4. 邮件失败 → SafeGiveUtil 安全掉落
⚠️ 建议

高价值物品(史诗/神话)建议配 MAIL_30DMAIL_180D,避免掉落。

💰 多货币与折扣 v1.1.0

多货币系统

后端说明依赖
vaultVault 经济接口Vault
playerpointsPlayerPoints 点券PlayerPoints
item物品货币
currencies:
  vault:
    display-name: "银币"
    backend: vault
  point:
    display-name: "金币"
    backend: playerpoints
  acoin:
    display-name: "A币"
    backend: item
    item-material: GOLD_NUGGET
    item-name: "&eA币"
  gem:
    display-name: "宝石"
    backend: item
    item-material: EMERALD

三层折扣

层级范围配置位置
A 层全局discount.permission-discounts
B 层商店级商店定义 discount
C 层商品级物品池 discount

叠加规则

模式说明
取最优best三层取最低(默认)
相乘multiply0.9 × 0.85 = 0.765
相加add折扣幅度相加
discount:
  enabled: true
  stack-mode: best
  min-rate: 0.5      # 不低于5折
  permission-discounts:
    vip:
      permission: "adventureshop.discount.vip"
      rate: 0.9
      priority: 10
    svip:
      permission: "adventureshop.discount.svip"
      rate: 0.8
      priority: 20

货币抵扣 v1.1.0

主货币不足时按比例用其他货币补差,聊天框弹出 [点击确认抵扣] 按钮。

currency-fallback:
  enabled: true
  rules:
    - from: vault      # 银币不足时
      to: point        # 用金币抵扣
      rate: 10.0       # 1金币 = 10银币
      max-ratio: 0.5   # 最多抵扣50%
    - from: vault
      to: gem
      rate: 100.0
      max-ratio: 1.0

🔗 插件联动

AdventureManage 联动

  • 金币交易自动走 AM 的 takeMoney / giveMoney
  • 交易记录带原因字符串
  • 出售给收购商店时自动按 AM 扣税
  • 未安装 AM 回退到 Vault 直接扣款

AdventureMail 联动

  • MAIL_7D / 30D / 180D 通道直接发送到邮箱
  • INVENTORY 背包满时自动转存邮箱 (默认 3 天)
  • 邮件标题自动标注商城信息
delivery:
  inventory-fallback:
    enabled: true
    mail-expire-days: 3
    mail-source: "§6[冒险商城] §7背包已满自动转存"

⌨️ 命令列表

玩家命令 /ashop

命令说明权限
/ashop打开分类选择 GUIadventureshop.use
/ashop <商店ID>直接打开指定商店adventureshop.use

管理命令 /ashopadmin

命令说明权限
/ashopadmin reload重载所有配置adventureshop.admin
/ashopadmin refresh <ID|all>强制刷新商店adventureshop.admin
/ashopadmin open <玩家> <ID>为玩家打开商店adventureshop.admin
/ashopadmin stats查看插件状态adventureshop.admin

⚙️ config.yml

核心设置

core:
  timezone: "Asia/Shanghai"

经济设置

economy:
  buy-back-ratio: 0.5
  rarity-price-multiplier:
    normal: 1.0
    advanced: 1.2
    rare: 1.5
    rarer: 2.0
    epic: 3.0
    mythical: 5.0

刷新设置

refresh:
  daily-time: "00:00"
  weekly-day: "MONDAY"
  monthly-day: 1
  player-refresh:
    cost-type: vault
    base-cost: 500
    cost-increase: 1.5
    max-per-day: 3

商店定义

shops:
  daySell-weapon:
    type: daySell
    category: weapon
    display-name: "今日热销-武器"
    item-count: 8
    rarity-weights:
      normal: 5
      advanced: 3
      rare: 2
      rarer: 1
      epic: 0.5
      mythical: 0

数据库

database:
  type: sqlite        # sqlite / mysql
  mysql:
    host: localhost
    port: 3306
    database: adventure_shop
    username: root
    password: ""
    pool-size: 5

🖥️ GUI 与消息配置

gui.yml

# 分类选择界面
category-gui:
  title: "§0§l冒险商城 §8| §r§6选择商店"
  size: 54

# 商店浏览界面
shop-gui:
  title-format: "§0§l冒险商城 §8| §r{shop_name} §7({page}/{total})"
  rows: 6
  item-slots: 45
  prev-page: { slot: 45, material: ARROW }
  next-page: { slot: 53, material: ARROW }
  refresh-button: { slot: 49, material: SUNFLOWER }
  info-button: { slot: 47, material: BOOK }

# 商品 Lore
item-display:
  name-format: "{rarity_color}[{rarity_name}] {item_name}"
  lore:
    sell:
      - "§7价格: §e{price} {currency}"
      - "§7全服库存: §f{global_stock}"
      - "§7个人限购: §f{purchased}/{player_limit}"
      - "§a▶ 左键购买"
    buy:
      - "§7收购价: §e{price} {currency}"
      - "§a▶ 左键出售"

messages.yml v1.2.2

所有用户可见消息、GUI 文本、日志、枚举显示名均可自定义。

分区用途
shop.*交易反馈 (购买/出售/刷新/抵扣)
reason.*交易原因 (AM 日志)
command.*命令反馈
gui.*GUI 标题/Lore/按钮
delivery.*发放结果
mail.*邮件标题/来源
log.*控制台日志
enum.*枚举显示名
prefix: "&6[冒险商城] &r"

shop:
  buy-success: "{prefix}&a成功购买 &e{item} &a! 花费 &e{price} {currency}"
  fallback-prompt: "{prefix}&e{currency}不足! ..."
  fallback-confirm-button: "&a&l[点击确认抵扣]"

enum:
  shop-type:
    day-sell: "今日热销"
  rarity:
    epic: "史诗"

🎨 GUI 界面

分类选择 GUI

/ashop 打开。每个商店一个图标:

商店类型图标
今日热销向日葵 SUNFLOWER
本周热销金苹果 GOLDEN_APPLE
本月精选下界之星 NETHER_STAR
固定出售箱子 CHEST
今日收购漏斗 HOPPER
本周收购漏斗矿车 HOPPER_MINECART
本月收购末影箱 ENDER_CHEST
固定收购木桶 BARREL

商店浏览 GUI

54 格界面 (6 行):第 1-5 行商品展示,第 6 行控制栏。

槽位功能
45上一页 (箭头)
47商店信息 (书本)
49刷新商店 (向日葵) — 费用+剩余次数
53下一页 (箭头)

🔑 权限节点

权限说明默认
adventureshop.use使用冒险商城所有人
adventureshop.admin管理员命令OP
adventureshop.refresh.N每日刷新 N 次 (1-10)false
adventureshop.discount.vipVIP 折扣 (9折)false
adventureshop.discount.svipSVIP 折扣 (8折)false
adventureshop.discount.mvpMVP 折扣 (7折)false
adventureshop.discount.*自定义折扣权限false
ℹ️ 刷新权限优先级

adventureshop.refresh.10 向下检查,使用首个匹配值。无权限时用 max-per-day

🗄️ 数据库与安全

存储引擎

SQLite (默认,零配置) 或 MySQL (HikariCP 连接池)。

数据表

表名用途
shop_items商品快照
player_purchases购买记录 (限购追踪)
player_refreshes刷新次数 (每日)
transactions交易日志
shop_stats商品统计

安全机制

GUI 防护

  • Shift / NumberKey / DoubleClick / Drop / SwapOffhand / Middle 全部拦截
  • InventoryDragEvent 阻止拖入
  • 只处理上方 GUI 区域点击

频率限制

操作限制
GUI 点击3秒 / 10次
购买/出售2秒 / 3次
刷新商店5秒 / 1次

库存原子操作

AtomicInteger + CAS 循环,并发安全不扣负。

交易安全

  • 购买:扣库存 → 扣钱 → 发物品,失败回滚
  • 出售:先给钱 → 成功后扣物品
  • 掉落:SafeGiveUtil 避开岩浆/虚空

📝 更新日志

v1.2.2 最新

  • NEW 消息外置 — 所有文本移至 messages.yml
  • NEW 枚举显示名 — 商店类型/稀有度可自定义名称

v1.1.0

  • NEW 多货币系统 — Vault/PlayerPoints/物品货币
  • NEW 三层折扣 — 全局/商店级/商品级
  • NEW 货币抵扣 — 主货币不足自动补差
  • NEW 4 种发放通道 — 背包/邮件 7/30/180 天
  • NEW AdventureMail 兜底 — 背包满自动转存

v1.0.0

  • NEW 初始发布 — 随机商品、稀有度、GUI、Vault 经济