BlockyDonations

BlockyDonations

Folia Paper 1.21+ PlaceholderAPI v1.0.8

Real-time webstore integration for Paper and Folia servers. Syncs purchases from Tebex, CraftingStore, MineStoreCMS and McSets, then broadcasts donations in-game, posts Discord embeds, tracks goals and exposes 40+ PlaceholderAPI placeholders.

Overview

BlockyDonations polls your webstore on a configurable interval and processes new purchases automatically. When a donation is detected it fires a configurable multi-line chat broadcast with optional player-head rendering, triggers a GG Wave reaction window, sends a Discord embed and updates all leaderboard and goal state.

Storage is handled by SQLite, MySQL or MariaDB - choose what fits your infrastructure. All polling and Discord requests run asynchronously so the main thread is never blocked. Folia threaded schedulers are detected and used automatically. Multi-server clustering is supported via database-backed leader election.

Supported Providers

  • Tebex
  • CraftingStore
  • MineStoreCMS
  • McSets

Optional Integrations

  • PlaceholderAPI - required for all %bd_*% placeholders
  • Floodgate - suppresses heads for Bedrock players
  • Chat Plugins - ChatControl, ZelChat, AdvancedChat compatibility

No restart needed. Run /bd reload after editing config.yml to apply changes immediately.

Installation

  1. Download BlockyDonations from BuiltByBit
  2. Place the JAR in your plugins/ folder
  3. Start or restart the server - default files generate automatically
  4. Edit plugins/BlockyDonations/config.yml with your store credentials
  5. Run /bd reload or restart again to activate
i

PlaceholderAPI required: Install PlaceholderAPI separately for %bd_*% placeholders to work in scoreboards, holograms and NPCs.

Configuration

Store Provider

config.yml
store:
  provider: "tebex"  # tebex | craftingstore | minestorecms | mcsets

  tebex:
    secret-key: "YOUR_TEBEX_SECRET_KEY_HERE"

  craftingstore:
    api-token: "YOUR_CRAFTINGSTORE_TOKEN_HERE"

  mcsets:
    api-key: "ss_YOUR_API_KEY_HERE"
    base-url: "https://app.mcsets.com/api/v1/setstore"

  minestorecms:
    secret-key: "YOUR_MINESTORECMS_SECRET_KEY_HERE"
    store-url: "https://store.yourserver.com"

Database

BlockyDonations can use SQLite (local file) or MySQL/MariaDB (external). MySQL enables multi-server clustering with automatic leader election.

config.yml
database:
  type: "sqlite"  # sqlite | mysql | mariadb

  sqlite:
    file: "donations.db"

  mysql:
    host: "127.0.0.1"
    port: 3306
    database: "blockydonations"
    username: "root"
    password: "change-me"
    use-ssl: false
    parameters: "useUnicode=true&characterEncoding=utf8&serverTimezone=UTC"

Sync Settings

config.yml
sync:
  interval: 120  # seconds between syncs (min 30)
  fetch-limit: 50   # max purchases per sync cycle

Broadcast Message

The broadcast is a YAML list - each entry is one chat line sent together. Player head rows ({player_head_1} through {player_head_8}) render the player's face texture alongside the text. All messages support full MiniMessage syntax including gradients, colors, hover effects and click events.

config.yml
broadcast:
  enabled: true
  message:
    - ' '
    - '{player_head_1}  <#FF8800>✦ <gradient:#FF8800:#FFD700><bold>New Donation!</bold></gradient>'
    - '{player_head_2}'
    - '{player_head_3}  <white>Player: <#FFD700>{player}'
    - '{player_head_4}  <white>Package: <#00BBFF>{package}'
    - '{player_head_5}  <white>Amount: <#49FF00>{amount_formatted}'
    - '{player_head_6}'
    - '{player_head_7}  <click:open_url:"https://store.servername.com"><hover:show_text:"<gold>Click to Open!"><#FFD700>Visit our store!</hover></click>'
    - '{player_head_8}  <white>Write <#FFD700>"GG" <white>in chat to celebrate! <#FF3232>❤'
    - ' '

  sound:
    enabled: true
    type: "ENTITY_PLAYER_LEVELUP"
    volume: 1.0
    pitch: 1.0

  head-render-type: "helm"  # helm (with hat) | avatar (raw face)

Broadcast Placeholders

variables
{player}                Player name
{package}               Package / product name
{amount}                Raw amount (e.g. 9.99)
{amount_formatted}      Amount with symbol (e.g. $9.99)
{currency}              ISO currency code
{currency_symbol}       Symbol (e.g. $)
{provider}              Store provider name
{store_name}            Store display name
{store_url}             Store URL
{store_url_encoded}     URL-encoded (use in open_url tags)
{player_head_1..8}      Full 8-pixel row (top=1, bottom=8)
{player_head}           Row 1 only (compact)
{player_face_url}       mc-heads.net avatar URL
{skin_minotar_avatar}   Minotar avatar URL
{skin_minotar_helm}     Minotar with hat
{skin_starlight_archer} StarlightSkins archer pose

Commands

Base command: /blockydonations - aliases: /bd, /blockydon, /d, /donations

/bd helpblockydonations.command.help
List all BlockyDonations commands.
/bd reloadblockydonations.command.reload
Reload config.yml and restart the sync cycle without a server restart.
/bd syncblockydonations.command.sync
Immediately trigger a manual sync with your webstore.
/bd test donationblockydonations.command.test
Fire a test donation broadcast with all effects, sounds and Discord embed.
/bd test goalblockydonations.command.test
Trigger a test goal-reached notification to verify Discord and in-game announcements.
/bd stats <player>blockydonations.command.stats
View total donated, monthly total and leaderboard rank for a player.
/bd top [alltime|monthly|recent]blockydonations.command.top
Display the in-game donation leaderboard. Defaults to alltime.
/bd goalsblockydonations.command.goals
Show current goal progress and completion count.
/bd salesblockydonations.command.sales
Display active sale information synced from your store.
/bd statusblockydonations.command.status
Show plugin status, connected store, sync health and latest donation info.
/bd updateblockydonations.command.update
Check for the latest version on BuiltByBit.

Permissions

Node Default Description
blockydonations.*opAll BlockyDonations permissions.
blockydonations.adminopAll admin commands: reload, sync, test, status, update.
blockydonations.command.reloadopUse /bd reload.
blockydonations.command.syncopUse /bd sync.
blockydonations.command.testopUse /bd test.
blockydonations.command.statusopUse /bd status.
blockydonations.command.toptrueUse /bd top - open to all players by default.
blockydonations.command.statsopUse /bd stats.
blockydonations.command.goalsopUse /bd goals.
blockydonations.command.salesopUse /bd sales.
blockydonations.command.updateopUse /bd update.

PlaceholderAPI

All placeholders require PlaceholderAPI to be installed. Every placeholder starts with %bd_.

Store Info

placeholders
%bd_store_name%               Store display name
%bd_store_url%                Store URL
%bd_store_currency%           Currency code (e.g. USD)
%bd_store_currency_symbol%    Currency symbol (e.g. $)
%bd_store_provider%           Provider name (e.g. tebex)

Latest Donation

placeholders
%bd_latest_player%            Donor username
%bd_latest_package%           Package name
%bd_latest_amount%            Raw amount
%bd_latest_amount_formatted%  Amount with symbol
%bd_latest_currency%          Currency code

Revenue

placeholders
%bd_revenue_total%            Total revenue (raw)
%bd_revenue_monthly%          Monthly revenue (raw)
%bd_revenue_total_formatted%  Total with symbol
%bd_revenue_monthly_formatted% Monthly with symbol

Leaderboards

Replace alltime with monthly or recent. Replace 1 with any rank from 1 to 10.

placeholders
%bd_top_alltime_1%            Rank 1 player name
%bd_top_alltime_1_amount%     Raw amount
%bd_top_alltime_1_formatted%  Amount with symbol
%bd_top_alltime_1_uuid%       Player UUID
%bd_top_alltime_1_skin%       Minotar head URL
%bd_top_alltime_1_skin_helm%  Helmet render URL
%bd_top_alltime_1_skin_avatar% Avatar render URL
%bd_top_alltime_1_skin_bust%  Bust render URL
%bd_top_alltime_1_skin_body%  Full body render URL

Player Statistics

placeholders
%bd_player_total%             Total donated (raw)
%bd_player_monthly%           Monthly total (raw)
%bd_player_recent%            Recent total (configurable days)
%bd_player_total_formatted%   Total with symbol
%bd_player_monthly_formatted% Monthly with symbol
%bd_player_recent_formatted%  Recent with symbol
%bd_player_rank_alltime%      Player's all-time leaderboard rank

Goals

placeholders
%bd_goal_name%                Goal name
%bd_goal_current%             Current progress (raw)
%bd_goal_target%              Target amount (raw)
%bd_goal_target_formatted%    Target with symbol
%bd_goal_percent%             Completion percentage
%bd_goal_remaining%           Amount remaining
%bd_goal_bar%                 Visual progress bar
%bd_goal_completed%           true / false
%bd_goal_completions%         Total times goal reached

Sales

placeholders
%bd_sale_name%                Active sale name
%bd_sale_discount%            Discount percentage
%bd_sale_active%              true / false

Broadcast

All broadcast text supports full MiniMessage syntax including gradients, hover events and click events. Player head rows use Minotar to sample the face texture and render it as Unicode characters across consecutive chat lines.

Head Render Type

config.yml
broadcast:
  head-render-type: "helm"  # helm (with hat layer) | avatar (raw face only)

Skin Render URLs

Use these in Discord embeds or custom messages:

variables
{skin_minotar_avatar}     Minotar avatar
{skin_minotar_helm}       Minotar with hat
{skin_minotar_bust}       Minotar bust
{skin_minotar_body}       Minotar full body
{skin_starlight_archer}   StarlightSkins archer pose
{skin_starlight_bust}     StarlightSkins bust
{skin_starlight_chibi}    StarlightSkins chibi

Chat Reactions (GG Wave)

A reaction window opens for all players after each donation. Players type reaction words (like "GG") to celebrate. Reactions can be styled with rainbow, gradient, or solid colors.

Basic Configuration

config.yml
chat-reactions:
  enabled: true
  listener-priority: "LOWEST"  # HIGHEST | HIGH | NORMAL | LOW | LOWEST
  window-seconds: 15
  min-amount: 2  # Minimum donation to trigger the wave (0 = no minimum)
  chance: 50  # 0-100 chance for wave to activate
  match-anywhere: true  # false = exact match, true = word appears anywhere
  case-sensitive: false

  words:
    - "gg"
    - "ggs"
    - "thank you"
    - "thanks"
    - "w"
    - "pog"
    - "poggers"

Text Formatting

config.yml
chat-reactions:
  format: "rainbow"  # rainbow | gradient | solid | solidrainbow

  rainbow:
    gradient: "#FF0000:#FF9A00:#FFF200:#00D26A:#8B00FF"
    gradient-smoothness: 8  # 2-32 (higher = smoother)

  solid-color: "#FFD700"

  solid-rainbow-colors:
    - "#FF0000"
    - "#FF7700"
    - "#FFFF00"
    - "#00FF00"
    - "#00FFFF"
    - "#0077FF"

  decorations:
    bold: true
    italic: false
    underline: false

Rewards

Execute commands when players type reaction words. Use {player} placeholder.

config.yml
chat-reactions:
  rewards:
    enabled: true
    commands:
      - "[CONSOLE] eco give {player} 100"
    run-once-per-wave: false  # true = player gets rewards only once per wave
    chance: 25  # 0-100 chance to run when reaction word is typed

Sounds

config.yml
chat-reactions:
  sounds:
    wave-start:
      enabled: true
      type: "item.goat_horn.sound.0"
      volume: 1.0
      pitch: 1.0
      category: "MASTER"

Regex Patterns

Match messages using Java regex for advanced customization. Patterns are tested before the word list.

config.yml
chat-reactions:
  patterns:
    - pattern: "(?i)^g+$"  # Match one or more 'g's (case insensitive)
      replace-with: "GG"
      color: "gradient"
      sound:
        type: "entity.player_levelup"
        volume: 1.0
        pitch: 1.2
        broadcast: true

Discord Webhook

Setup

  1. Open Discord server settings, go to Integrations, then Webhooks.
  2. Create a new webhook, choose a channel, copy the URL.
  3. Create a separate webhook for goals (optional).
  4. Paste URLs into discord.yml.
  5. Run /bd reload.

Donation Embed

discord.yml
discord:
  enabled: false
  webhook-url: "https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"

  donation-embed:
    title: "New Donation! 🎉"
    description: "**{player}** donated **{currency_symbol}{amount}** for **{package}**!\nThank you for supporting the server! ❤️"
    color: "#36CC00"
    footer: "Server Goal: {goal_percent}% / 100% {goal_bar}"

    timestamp:
      enabled: true

    author:
      enabled: true  # Shows donator's head and name

    image:
      provider: "starlight"  # minotar | starlight | none
      placement: "image"  # thumbnail | image | description | none

      minotar:
        type: "helm"  # avatar | helm | bust | body | skin
        size: 128

      starlight:
        type: "random"  # archer | bust | chibi | portrait | default | etc

    branding-images:
      - url: "https://leafstudios.dev/images/logo_small.png"
        placement: "thumbnail"

Goal Reached Embed

Sent to a separate webhook channel when the server reaches its monthly goal.

discord.yml
discord:
  goal-embed:
    enabled: true
    title: "🎉 Goal Reached! 🎉"
    description: "Thanks to **{latest_donator}** and everyone who donated.\n\nWe've reached our goal of **{goal_target_formatted}**!\nThis is completion #**{goal_completions}**. Y'all are amazing! ❤️\n\nAll-time top donor: **{top_donator}** ({top_donator_amount})"
    color: "#FFD700"
    footer: "Server Goal: 100% 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩"
    timestamp:
      enabled: true

Discord sends are queued and dispatched at most once per second to avoid rate limits.

Leaderboards

Three leaderboard types are maintained independently:

  • alltime - total donations since install
  • monthly - current calendar month, resets on the 1st
  • recent - past N days, configured via leaderboard.recent-days
config.yml
leaderboard:
  size: 10  # Show top 10 players
  recent-days: 7  # "recent" leaderboard looks back 7 days

Use /bd top to display a leaderboard in-game, or reference values in holograms and scoreboards via PlaceholderAPI placeholders.

Goals

i

Auto-fetched from your store. BlockyDonations automatically detects and uses goals configured in your store provider (Tebex, CraftingStore, MineStoreCMS, McSets). If a goal is set in your store, it will be synchronized automatically — no manual config needed.

Set a monetary target for your community to reach each month. When the goal is completed, BlockyDonations fires an in-game announcement and sends a dedicated Discord embed.

config.yml
goals:
  track-completions: true  # Track how many times goal was reached
  announce-in-chat: true  # Show in-game announcement when goal reached
  progress-bar-length: 25

  progress-bar-style: "pipes"  # blocks | pipes | custom

  progress-bar-filled: "█"
  progress-bar-empty: "█"

  progress-bar-color-filled: "<green><b>"
  progress-bar-color-empty: "<gray><b>"

Effects

Visual and audio effects that fire for all online players when a donation is detected.

Fireworks

config.yml
effects:
  firework:
    enabled: true
    type: BALL_LARGE  # BALL | BALL_LARGE | BURST | CREEPER | STAR
    power: 1  # 0-4 (higher = longer fuse / goes higher)
    flicker: true
    trail: true
    colors:
      - ORANGE
      - YELLOW
    fade-colors: []  # Leave empty to use same as colors

Lightning & Title

config.yml
effects:
  lightning:
    enabled: false
    damaging: false  # Visual only (true = deals damage)

  title:
    enabled: false
    title: "<gradient:#FF8800:#FFD700><bold>✦ New Donation! ✦</bold></gradient>"
    subtitle: "<#FFD700>{player} <white>donated <#49FF00>{amount_formatted}</white>!"
    fade-in: 10  # ticks (20 = 1 second)
    stay: 60
    fade-out: 20