BlackMarket

BlackMarket

Folia 1.19 to 1.21+ PlaceholderAPI v2.0.7

Underground trading system with timed item rotations, per-item cooldowns, stock limits, category filtering, GUI pagination, Redis cross-server synchronisation and support for Vault, PlayerPoints and CoinsEngine economies.

Overview

BlackMarket presents players with a rotating set of items in a chest GUI that resets on a configurable interval. Items can have individual cooldowns, stock limits, one-time purchase restrictions, expiry times and spawn chances. Categories allow players to filter the market. Pagination handles large item pools cleanly.

Data is stored in SQLite by default. MySQL is supported for networked setups. Redis can be enabled for real-time cross-server market synchronisation on BungeeCord or Velocity networks.

Soft Dependencies

  • Vault — economy support
  • PlayerPoints — points-based economy
  • CoinsEngine — coins economy
  • PlaceholderAPI — item lore and display name placeholders
  • LuckPerms — per-item permission checks

Folia supported. BlackMarket detects Folia automatically and uses threaded schedulers where required.

Installation

  1. Download BlackMarket from BuiltByBit
  2. Place the JAR in your plugins/ folder
  3. Start or restart the server — config.yml, items.yml and messages.yml generate automatically
  4. Edit plugins/BlackMarket/config.yml and plugins/BlackMarket/items.yml
  5. Run /bma reload or restart to apply
i

Vault must be installed for the default vault economy to work. Install your preferred economy plugin before starting.

Configuration

Market Settings

config.yml
market:
  global-market:    true    # all players see the same items
  reset-interval:   24h     # supports s, m, h, d
  items-per-reset:  5
  send-reset-message: true

GUI

config.yml
gui:
  title:              "&8&lBlack Market"
  rows:               6
  close-on-purchase:  false
  enable-categories:  true
  pagination:
    enabled:       true
    title-format:  " &8- &7Page %page%/%total%"

Sounds

config.yml
sounds:
  gui-open:         BLOCK_CHEST_OPEN
  gui-close:        BLOCK_CHEST_CLOSE
  purchase-success: ENTITY_PLAYER_LEVELUP
  purchase-fail:    ENTITY_VILLAGER_NO
  click:            UI_BUTTON_CLICK
  page-turn:        ITEM_BOOK_PAGE_TURN

Lore Status Lines

Each status type (stock, out-of-stock, cooldown, expiry, etc.) has configurable lore lines that appear dynamically on item stacks in the GUI.

config.yml
lore:
  stock:
    enabled: true
    lines:   ["&7Stock: &e%stock_remaining%&7/&e%stock_max%"]
  cooldown:
    enabled: true
    lines:   ["&c&lON COOLDOWN &7— &e%cooldown_time% remaining"]
  expires-in:
    enabled: true
    lines:   ["&eExpires in: &f%expire_time%"]

Items

All market items live in plugins/BlackMarket/items.yml. Each item is a named key under items:.

Item Properties

Key Description
materialBukkit material name (e.g. DIAMOND_SWORD).
display-nameGUI display name. Supports MiniMessage and legacy codes.
loreList of lore lines.
pricePurchase price.
economy-typevault, playerpoints, coinsengine or exp.
commandConsole command on purchase. Use %player%.
messageCustom purchase message sent to buyer.
categoryCategory string for the filter button.
stockMax stock. Use -1 for unlimited.
one-timetrue — item can only be purchased once per player.
cooldownTime between purchases per player (e.g. 1h, 30m).
expiryTime until item expires from the market (e.g. 12h, 1d).
permissionPermission node required to purchase.
chance0 to 100 — probability the item appears in a rotation.
soundSound played on purchase.
effectParticle effect spawned on purchase.
custom-model-dataResource pack model data integer.

Example Item

items.yml
items:
  diamond_sword:
    material:      "DIAMOND_SWORD"
    display-name:  "&b&lEnchanted Diamond Sword"
    lore:
      - "&7Price: &e$50,000"
      - "&6Chance: &e%item_chance%%"
      - "&e&l▶ CLICK TO PURCHASE"
    price:         50000
    economy-type:  "vault"
    command:       "give %player% diamond_sword 1"
    category:      "Weapons"
    stock:         10
    cooldown:      "1h"
    expiry:        "12h"
    permission:    "blackmarket.buy.diamond_sword"
    chance:        100
    sound:         "ENTITY_PLAYER_LEVELUP"
    effect:        "VILLAGER_HAPPY"

Commands

Player Commands

/blackmarketblackmarket.use
Open the Black Market GUI. Aliases: /bm, /market, /illegalmarket, /illegalstore.

Admin Commands

Base: /blackmarketadmin — aliases /bma, /marketadmin

/bma reload [config|messages|lang|items|all]blackmarket.admin.reload
Reload one or all config files. Omit the argument to reload everything.
/bma resetblackmarket.admin.reset
Force an immediate market reset with a new item selection.
/bma open <player>blackmarket.admin.open
Open the market for a specific player.
/bma infoblackmarket.admin.info
Display plugin information, version and current market state.
/bma debugblackmarket.admin.debug
Toggle debug mode for detailed console logging.

Permissions

Node Default Description
blackmarket.*opAll BlackMarket permissions.
blackmarket.usetrueOpen the market.
blackmarket.adminopAll admin commands.
blackmarket.admin.reloadopUse /bma reload.
blackmarket.admin.resetopUse /bma reset.
blackmarket.admin.openopUse /bma open.
blackmarket.admin.infoopUse /bma info.
blackmarket.admin.debugopUse /bma debug.
blackmarket.bypass.cooldownopBypass per-item cooldowns.
blackmarket.bypass.stockopBuy items even when out of stock.
blackmarket.bypass.permissionopBypass item permission requirements.

Economy

The default economy is set globally in config.yml and can be overridden per item in items.yml.

config.yml
economy:
  default: "vault"  # vault | playerpoints | coinsengine | exp

Per-item override — set economy-type on any item in items.yml to use a different currency for that item only.

Database

config.yml
database:
  type: "sqlite"  # sqlite | mysql
  mysql:
    host:     "localhost"
    port:     3306
    database: "blackmarket"
    username: "root"
    password: "password"
    use-ssl:  false

SQLite stores data locally in plugins/BlackMarket/data.db. No external server is needed. Switch to MySQL for shared data across a network without Redis.

Redis

Enable Redis for real-time market state synchronisation across multiple servers on BungeeCord or Velocity networks. All servers share the same market rotation, stock levels and cooldowns.

config.yml
redis:
  enabled:   false
  server-id: "server-1"   # unique per server in your network
  host:      "localhost"
  port:      6379
  password:  ""
  database:  0
  use-ssl:   false
  pool:
    max-total: 8
    max-idle:  8
    min-idle:  0
i

Each server must have a unique server-id. Redis pub/sub is used to broadcast market events so all servers react instantly.