WIP: Add ServerShop plugin — server-run global market with configurable pricing #2

Draft
Copilot wants to merge 3 commits from copilot/add-server-shop-plugin into main
Copilot commented 2026-02-22 10:49:26 +00:00 (Migrated from github.com)

Standalone server-run shop plugin designed to complement CommunityMarket's player-to-player economy. Uses a large configurable buy/sell spread (default 75%) so players still prefer trading via CommunityMarket.

Plugin architecture (ServerShop/)

  • Core: ServerShop.java main class, ShopCommand (/shop, /servershop), Vault economy integration with graceful failure
  • Pricing: Config-driven PricingService with per-category sell multipliers (sellPrice = buyPrice * 0.25), per-item overrides, buy/sell toggles
  • GUI system: MainShopGuiCategoryGui (paginated) → ItemDetailGui (quantity selector: ±1/8/16/32, MIN/MAX, buy/sell confirm). Search via chat input → SearchResultsGui
  • Anti-exploit: GuiListener blocks shift-click, number key swap, drag, double-click, off-hand swap. ShopService re-validates balance and inventory at transaction time
  • Storage: Async SQLite transaction logging via TransactionLogger
  • i18n: en_US.yml + pt_PT.yml with {placeholder} system and message caching

Resources

  • prices.yml — 10 categories, ~400 items with sensible default prices
  • config.yml — economy, GUI, sound, logging, and behavior settings
  • plugin.yml — depends on Vault, registers /shop command and 7 permission nodes

Key design decisions

  • Separate Maven project in ServerShop/ — no changes to existing CommunityMarket code
  • Static pricing only (v1) — no dynamic supply/demand; deterministic and config-driven
  • Special meta items (enchanted books, potions) excluded by default, configurable via pricing.include-special-items
  • Full inventory handling: configurable DROP at feet vs CANCEL purchase

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • jitpack.io
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket/ServerShop org.codehaus.plexus.classworlds.launcher.Launcher clean compile (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher clean compile (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)
  • repo.papermc.io
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket/ServerShop org.codehaus.plexus.classworlds.launcher.Launcher clean compile (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher clean compile (dns block)
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

You are an expert Paper/Purpur plugin developer. Build a professional Server Shop / Global Market plugin for Paper/Purpur 1.21.11 using Java 21 and Maven.

Project goal:
This is a server-run market (NOT player-to-player). It exists alongside my player marketplace plugin (CommunityMarket) and must be designed to support it economically by having a large spread between buy and sell prices (so players still prefer selling to other players).

Core concept:

  • Every item/block in the game is available for buy and/or sell.
  • Prices are configurable and category-based.
  • Fully GUI-driven with categories, search, pagination, and quantity selection.
  • Uses Vault economy (required).
  • Clean, documented, Modrinth-ready.

================================================================================

  1. Technical requirements (MUST)
    ================================================================================
  • Target: Paper/Purpur 1.21.11
  • Java: 21
  • Maven project (pom.xml + full source)
  • Vault economy integration (required). Fail gracefully if missing.
  • SQLite for optional logging/stats (optional). YAML is ok if simpler.
  • Async where appropriate; no main-thread blocking for file/DB I/O.
  • Robust GUI handling (no dupes, cancel illegal clicks, validate everything server-side).
  • Strong code documentation (JavaDoc for public classes, comments for tricky logic).

================================================================================
2) GUI-only UX (MUST)

Commands:

  • Only /shop (alias /servershop) opens the main GUI.
    No other required commands for players; all interactions in GUI.

Main GUI:

  • Category buttons (e.g., Blocks, Ores, Farming, Food, Mob Drops, Redstone, Decoration, Tools, Combat, Brewing, Misc).
  • Search button (GUI-driven; anvil input allowed).
  • “Sell inventory” / “Sell hand” buttons (optional, but must confirm).

Category GUI:

  • Paginated grid of items.
  • Sorting options (optional): price asc/desc, alphabetical.
  • Each item shows:
    • Buy price
    • Sell price
    • Spread indicator (e.g., “Server spread: 60%”)

Item Detail GUI:

  • Shows item, buy/sell prices, wallet balance.
  • Quantity selector:
    • -1/-8/-16/-32 on left
    • +1/+8/+16/+32 on right
    • MIN / MAX buttons
  • Buy confirm and Sell confirm buttons (separate)
  • Clear messages on success/failure.

================================================================================
3) Pricing model (MUST)

We want a large gap between buy and sell prices to keep CommunityMarket valuable.

Implement pricing rules:

  • Each item has:
    • buyPrice (server sells to player)
    • sellPrice (server buys from player)
  • Default behavior:
    • sellPrice = buyPrice * sellMultiplier where multiplier is LOW (e.g., 0.25) — configurable globally and per-category.
  • Allow overrides per item:
    • explicit buy/sell prices
    • ability to disable selling or buying for certain items.

Important:

  • Do NOT use dynamic supply/demand pricing in v1 unless it’s simple and safe.
  • Keep it deterministic and config-driven.

================================================================================
4) Item coverage (MUST)

  • Include ALL items/blocks from the game:
    • Use Material enumeration for 1.21.11.
  • Provide sensible default categories mapping:
    • A category map in config that assigns Materials to categories.
  • The plugin must still function if new items are added (fallback category: Misc).

Exclude/handle:

  • Air and invalid materials should not appear.
  • Items with special meta (enchanted books, potions) can be:
    • either excluded by default OR included with base pricing (configurable).
      State the decision clearly and make it configurable.

================================================================================
5) Buy and Sell mechanics (MUST)

Buying:

  • Validate player has enough money.
  • Add items to inventory; if full:
    • either drop safely at player feet OR prevent purchase (configurable).
  • Charge via Vault.

Selling:

  • Validate player has the required quantity in inventory (exact material match).
  • Remove items safely server-side.
  • Pay via Vault.
  • Optionally apply tax/fee (configurable).
  • Provide “sell all of this material” shortcut (optional) with confirmation.

Anti-exploit:

  • Handle shift-click, number key swaps, drag events, double-click.
  • Re-check balance and inventory at confirm time.
  • No duplication vulnerabilities.

================================================================================
6) Configurability (MUST)

Provide config.yml with:

  • language: en_US default + pt_PT opti...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Standalone server-run shop plugin designed to complement CommunityMarket's player-to-player economy. Uses a large configurable buy/sell spread (default 75%) so players still prefer trading via CommunityMarket. ## Plugin architecture (`ServerShop/`) - **Core**: `ServerShop.java` main class, `ShopCommand` (`/shop`, `/servershop`), Vault economy integration with graceful failure - **Pricing**: Config-driven `PricingService` with per-category sell multipliers (`sellPrice = buyPrice * 0.25`), per-item overrides, buy/sell toggles - **GUI system**: `MainShopGui` → `CategoryGui` (paginated) → `ItemDetailGui` (quantity selector: ±1/8/16/32, MIN/MAX, buy/sell confirm). Search via chat input → `SearchResultsGui` - **Anti-exploit**: `GuiListener` blocks shift-click, number key swap, drag, double-click, off-hand swap. `ShopService` re-validates balance and inventory at transaction time - **Storage**: Async SQLite transaction logging via `TransactionLogger` - **i18n**: `en_US.yml` + `pt_PT.yml` with `{placeholder}` system and message caching ## Resources - `prices.yml` — 10 categories, ~400 items with sensible default prices - `config.yml` — economy, GUI, sound, logging, and behavior settings - `plugin.yml` — depends on Vault, registers `/shop` command and 7 permission nodes ## Key design decisions - **Separate Maven project** in `ServerShop/` — no changes to existing CommunityMarket code - **Static pricing only** (v1) — no dynamic supply/demand; deterministic and config-driven - **Special meta items** (enchanted books, potions) excluded by default, configurable via `pricing.include-special-items` - **Full inventory handling**: configurable DROP at feet vs CANCEL purchase > [!WARNING] > > <details> > <summary>Firewall rules blocked me from connecting to one or more addresses (expand for details)</summary> > > #### I tried to connect to the following addresses, but was blocked by firewall rules: > > - `jitpack.io` > - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket/ServerShop org.codehaus.plexus.classworlds.launcher.Launcher clean compile` (dns block) > - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher clean compile` (dns block) > - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip` (dns block) > - `repo.papermc.io` > - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket/ServerShop org.codehaus.plexus.classworlds.launcher.Launcher clean compile` (dns block) > - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher clean compile` (dns block) > - Triggering command: `/usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.12/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.12/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.12 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.12/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/CommunityMarket/CommunityMarket org.codehaus.plexus.classworlds.launcher.Launcher -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip` (dns block) > > If you need me to access, download, or install something from one of these locations, you can either: > > - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled > - Add the appropriate URLs or hosts to the custom allowlist in this repository's [Copilot coding agent settings](https://github.com/henriquescrrrr/CommunityMarket/settings/copilot/coding_agent) (admins only) > > </details> <!-- START COPILOT CODING AGENT SUFFIX --> <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> You are an expert Paper/Purpur plugin developer. Build a professional **Server Shop / Global Market** plugin for **Paper/Purpur 1.21.11** using **Java 21** and **Maven**. Project goal: This is a **server-run market** (NOT player-to-player). It exists alongside my player marketplace plugin (CommunityMarket) and must be designed to **support** it economically by having a **large spread** between buy and sell prices (so players still prefer selling to other players). Core concept: - Every item/block in the game is available for **buy** and/or **sell**. - Prices are configurable and category-based. - Fully GUI-driven with categories, search, pagination, and quantity selection. - Uses Vault economy (required). - Clean, documented, Modrinth-ready. ================================================================================ 1) Technical requirements (MUST) ================================================================================ - Target: Paper/Purpur 1.21.11 - Java: 21 - Maven project (pom.xml + full source) - Vault economy integration (required). Fail gracefully if missing. - SQLite for optional logging/stats (optional). YAML is ok if simpler. - Async where appropriate; no main-thread blocking for file/DB I/O. - Robust GUI handling (no dupes, cancel illegal clicks, validate everything server-side). - Strong code documentation (JavaDoc for public classes, comments for tricky logic). ================================================================================ 2) GUI-only UX (MUST) ================================================================================ Commands: - Only `/shop` (alias `/servershop`) opens the main GUI. No other required commands for players; all interactions in GUI. Main GUI: - Category buttons (e.g., Blocks, Ores, Farming, Food, Mob Drops, Redstone, Decoration, Tools, Combat, Brewing, Misc). - Search button (GUI-driven; anvil input allowed). - “Sell inventory” / “Sell hand” buttons (optional, but must confirm). Category GUI: - Paginated grid of items. - Sorting options (optional): price asc/desc, alphabetical. - Each item shows: - Buy price - Sell price - Spread indicator (e.g., “Server spread: 60%”) Item Detail GUI: - Shows item, buy/sell prices, wallet balance. - Quantity selector: - -1/-8/-16/-32 on left - +1/+8/+16/+32 on right - MIN / MAX buttons - Buy confirm and Sell confirm buttons (separate) - Clear messages on success/failure. ================================================================================ 3) Pricing model (MUST) ================================================================================ We want a **large gap** between buy and sell prices to keep CommunityMarket valuable. Implement pricing rules: - Each item has: - `buyPrice` (server sells to player) - `sellPrice` (server buys from player) - Default behavior: - `sellPrice = buyPrice * sellMultiplier` where multiplier is LOW (e.g., 0.25) — configurable globally and per-category. - Allow overrides per item: - explicit buy/sell prices - ability to disable selling or buying for certain items. Important: - Do NOT use dynamic supply/demand pricing in v1 unless it’s simple and safe. - Keep it deterministic and config-driven. ================================================================================ 4) Item coverage (MUST) ================================================================================ - Include ALL items/blocks from the game: - Use Material enumeration for 1.21.11. - Provide sensible default categories mapping: - A category map in config that assigns Materials to categories. - The plugin must still function if new items are added (fallback category: Misc). Exclude/handle: - Air and invalid materials should not appear. - Items with special meta (enchanted books, potions) can be: - either excluded by default OR included with base pricing (configurable). State the decision clearly and make it configurable. ================================================================================ 5) Buy and Sell mechanics (MUST) ================================================================================ Buying: - Validate player has enough money. - Add items to inventory; if full: - either drop safely at player feet OR prevent purchase (configurable). - Charge via Vault. Selling: - Validate player has the required quantity in inventory (exact material match). - Remove items safely server-side. - Pay via Vault. - Optionally apply tax/fee (configurable). - Provide “sell all of this material” shortcut (optional) with confirmation. Anti-exploit: - Handle shift-click, number key swaps, drag events, double-click. - Re-check balance and inventory at confirm time. - No duplication vulnerabilities. ================================================================================ 6) Configurability (MUST) ================================================================================ Provide `config.yml` with: - language: en_US default + pt_PT opti... </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
henriquescrrrr (Migrated from github.com) reviewed 2026-02-22 10:49:26 +00:00
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin copilot/add-server-shop-plugin:copilot/add-server-shop-plugin
git checkout copilot/add-server-shop-plugin
Sign in to join this conversation.