高级商店

高级商店

一个Kubejs附加组件,允许你创建商店并运行世界事件

🛒 高级商店

高级商店是一个以 KubeJS 为先的商店系统,专为需要超越基础买卖菜单的整合包而设计。

创建整洁的商店分类、注册自定义条目、将物品锁在进度之后、根据购买量动态调整价格,并运行带自定义效果的限时抢购活动。它对于小型商店保持简洁,同时为整合包作者提供足够的控制力,以构建完整的经济系统、季节性活动和以进度为核心的游戏玩法。

✨ 功能特性

  • 📦 完全通过 KubeJS 注册购买和出售条目
  • 🗂️ 创建带有图标、排序和可见性设置的自定义分类
  • 💰 为每个条目设置价格、数量、NBT、悬停主题和排序
  • 📈 添加购买限制和动态定价
  • 🔒 将条目锁定在玩家进度检查之后
  • ⚡ 对分类或带标签的商店条目运行限时抢购
  • 🧩 通过 KubeJS 事件 挂钩商店活动
  • 🎯 非常适合教程、战利品箱、资源交换、改装品和限时活动

🧪 简单的 KubeJS 示例

📁 创建分类

ServerEvents.superiorShopCategories(event => {
  event.category('starter', cat => {
    cat.title('新手补给') // 商店中显示的名称
    cat.icon('minecraft:emerald') // 分类使用的图标
    cat.order(0) // 数字越小越靠前
    cat.hidden(false) // 设置为 true 以隐藏该分类
  })
})

🛍️ 添加基础购买和出售条目

ServerEvents.superiorShopItems(event => {
  const starter = event.category('starter') // 通过 id 获取分类

  starter.item('minecraft:bread', 'buy', 5) // 物品 id、方向、基础价格
    .hoverTheme('light_green') // 可选的条目颜色/主题
    .order(0) // 在分类中的可选排序位置

  starter.item('minecraft:rotten_flesh', 'sell', 2) // 出售条目示例
    .hoverTheme('dark_red')
    .order(1)
})

📈 添加带动态定价的限购物品

ServerEvents.superiorShopItems(event => {
  event.category('starter')
    .item('minecraft:golden_apple', 'buy', 25)
    .limit(5) // 每个玩家只能购买此条目 5 次
    .scalingMultiply(1.5) // 每次购买后价格乘以 1.5
    .scalingRound('ceil') // 将新价格向上取整
    .scalingMax(200) // 价格最高不超过 200
    .hoverTheme('gold')
})

🔒 在玩家解锁前隐藏条目

ServerEvents.superiorShopItems(event => {
  event.category('starter')
    .item('minecraft:elytra', 'buy', 2500)
    .visibleIf(player => player.persistentData.getBoolean('killed_dragon'))
    // 仅在玩家数据标记为 true 时显示
    .hoverTheme('light_blue')
})

⚡ 标记条目并运行限时抢购

ServerEvents.superiorShopItems(event => {
  event.category('starter')
    .item('minecraft:iron_pickaxe', 'buy', 40)
    .entryTag('mining_fever') // 标签允许促销活动针对此条目
})

SuperiorShop.startSale('mining_fever', 120, sale => { // 120 是活动持续秒数
  sale.message('采矿狂热:带标签物品 2 分钟内 5 折!')
  sale.affectEntryTag('mining_fever', rule => rule.mulBuyPrice(0.5))
  // 活动期间,任何带此标签的条目都享受折扣
})

🎁 响应购买或出售事件

ServerEvents.superiorShopBuyEntry(event => {
  // 每当玩家从商店购买时触发
  event.player.tell(`你花费了 ${event.totalPrice} 商店货币。`)
})

ServerEvents.superiorShopSellEntry(event => {
  // 每当玩家向商店出售时触发
  if (event.totalPrice >= 100) {
    // 示例:为大额交易提供小额奖励
    Utils.server.runCommandSilent(`/superior_shop add ${event.player.username} 10`)
  }
})

🧱 数据驱动的商店示例

// 分类定义在一个对象中,便于编辑商店布局。
const SHOP_CATEGORIES = {
  starter_supplies: {
    title: '新手补给',
    icon: 'minecraft:bread',
    order: 0,
    hidden: false,
  },

  mob_drops: {
    title: '生物掉落物',
    icon: 'minecraft:bone',
    order: 1,
    hidden: false,
  },

  special_offers: {
    title: '特别优惠',
    icon: 'minecraft:golden_apple',
    order: 2,
    hidden: false,
  },
}

// 物品按分类分组,然后在循环中注册。
const SHOP_ITEMS = {
  starter_supplies: {
    defaults: {
      side: 'buy', // 此分类下大部分条目是购买条目
      hoverTheme: 'light_green',
    },
    entries: [
      {
        item: 'minecraft:bread',
        price: 5,
        quantity: 8, // 购买此条目获得 8 个面包
      },
      {
        item: 'minecraft:torch',
        price: 3,
        quantity: 16,
      },
      {
        item: 'minecraft:iron_pickaxe',
        price: 40,
        entryTag: 'starter_sale', // 允许限时抢购针对此条目
      },
    ],
  },

  mob_drops: {
    defaults: {
      side: 'sell', // 此分类下大部分条目是出售条目
      hoverTheme: 'dark_red',
    },
    entries: [
      {
        item: 'minecraft:rotten_flesh',
        price: 2,
      },
      {
        item: 'minecraft:bone',
        price: 3,
      },
      {
        item: 'minecraft:string',
        price: 4,
      },
    ],
  },

  special_offers: {
    defaults: {
      side: 'buy',
      hoverTheme: 'gold',
    },
    entries: [
      {
        item: 'minecraft:golden_apple',
        price: 25,
        id: 'special_golden_apple', // 此商店条目的自定义 id
        limit: 5, // 只能购买 5 次
        scalingPrice: {
          mode: 'multiply',
          factor: 1.5, // 每次购买后价格乘以 1.5
          round: 'ceil',
          max: 200, // 价格永远不会超过 200
        },
      },
      {
        item: 'minecraft:enchanted_book',
        price: 150,
        nbt: '{StoredEnchantments:[{id:"minecraft:unbreaking",lvl:3s}]}',
        // 出售特定 NBT 物品的示例
      },
      {
        item: 'minecraft:elytra',
        price: 2500,
        visibleIf: player => player.persistentData.getBoolean('killed_dragon'),
        // 仅当在 KubeJS 其他位置设置此玩家数据标记时显示
      },
    ],
  },
}

ServerEvents.superiorShopCategories(event => {
  Object.entries(SHOP_CATEGORIES).forEach(([id, data]) => {
    event.category(id, cat => {
      cat.title(data.title)
      cat.icon(data.icon)
      cat.order(data.order)
      cat.hidden(data.hidden)
    })
  })
})

function applyShopEntry(builder, entry, index, defaults) {
  const hoverTheme = entry.hoverTheme ?? defaults.hoverTheme
  const side = entry.side ?? defaults.side

  if (entry.id) builder.id(entry.id)
  if (entry.nbt) builder.nbt(entry.nbt)
  if (hoverTheme) builder.hoverTheme(hoverTheme)
  if (entry.entryTag) builder.entryTag(entry.entryTag)
  if (entry.quantity !== undefined) builder.quantity(entry.quantity)
  if (entry.limit !== undefined) builder.limit(entry.limit)

  if (entry.scalingPrice) {
    const scaling = entry.scalingPrice
    if (scaling.mode === 'multiply') builder.scalingMultiply(scaling.factor)
    if (scaling.round) builder.scalingRound(scaling.round)
    if (scaling.max !== undefined) builder.scalingMax(scaling.max)
  }

  if (entry.visibleIf) builder.visibleIf(entry.visibleIf)

  builder.order(entry.order ?? index)
}

ServerEvents.superiorShopItems(event => {
  Object.entries(SHOP_ITEMS).forEach(([categoryId, categoryData]) => {
    const category = event.category(categoryId)
    const defaults = categoryData.defaults || {}

    categoryData.entries.forEach((entry, index) => {
      const side = entry.side ?? defaults.side ?? 'buy'
      const builder = category.item(entry.item, side, entry.price)
      applyShopEntry(builder, entry, index, defaults)
    })
  })
})