Files
CustomNPC-Plus/1.11_Market_Update.md
T
2026-01-24 16:03:54 -05:00

31 KiB

CustomNPC+ 1.11 Market Update - Implementation Plan

Overview

The 1.11 Market Update introduces a comprehensive economy system for CustomNPC+:

  1. Currency System - Built-in CNPC+ currency with optional Vault integration
  2. Trader Enhancements - Stock system, currency-based trades, reset timers
  3. Auction House - Global auction system with bidding, buyout, and claims

1. Currency System

Status: COMPLETE ✅

The currency system provides a unified economy for CNPC+ features.

Features

  • Built-in CNPC+ Currency - Stored in PlayerData, persists across profile slots
  • Vault Integration - Optional, when enabled all operations use Vault instead
  • Scripting API - Full access via IPlayer methods
  • Unified Usage - Both Trader and Auction systems use PlayerCurrencyData which auto-delegates to Vault

Vault Integration Flow

┌─────────────────────────────────────────────────────────────────┐
│                    PlayerCurrencyData                            │
│                                                                  │
│  shouldUseVault() = ConfigMarket.UseVault && VaultUtil.isEnabled()│
│                                                                  │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ All methods check shouldUseVault() first:                    │ │
│  │   - getBalance() → VaultUtil.getBalance() or local balance   │ │
│  │   - withdraw()   → VaultUtil.withdrawMoney() or local        │ │
│  │   - deposit()    → VaultUtil.addMoney() or local             │ │
│  │   - canAfford()  → VaultUtil.has() or local check            │ │
│  └─────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  Used by: ContainerNPCTrader, AuctionController                  │
└─────────────────────────────────────────────────────────────────┘

Key Files

File Purpose
PlayerTradeData.java Per-player trade data (currency + auction claims), Vault delegation
IPlayerTradeData.java API interface for trade operations (currency + claims)
ConfigMarket.java Currency configuration (UseVault, CurrencyName, StartingBalance, MaxBalance)
VaultUtil.java Vault API integration via reflection

Configuration (ConfigMarket.java)

Market.Currency:
  - Use Vault: false
  - Currency Name: "Coins"
  - Starting Balance: 0
  - Max Balance: 2147483647

Scripting API (IPlayer)

player.getCurrencyBalance()        // Get balance
player.setCurrencyBalance(amount)  // Set balance
player.depositCurrency(amount)     // Add currency (returns success)
player.withdrawCurrency(amount)    // Remove currency (returns success)
player.canAffordCurrency(amount)   // Check if can afford
player.isUsingVaultCurrency()      // Check if Vault is active
player.getFormattedCurrencyBalance() // Get formatted string

// Via IPlayerData
player.getData().getTradeData()    // Get IPlayerTradeData interface

2. Trader Enhancements

Status: COMPLETE ✅


2.1 Stock System - COMPLETE ✅

Traders can have limited stock that resets on configurable schedules.

Stock Modes

Mode Description Status
Global All players share the same stock pool ✅ Working
Per-Player Each player has their own stock counts ✅ Working

Stock Reset Types (EnumStockReset)

Type Description Status
NONE Stock never resets ✅ Working
MCDAILY Resets every MC day (24000 ticks) ✅ Working
MCWEEKLY Resets every 7 MC days (168000 ticks) ✅ Working
MCCUSTOM Custom MC tick interval ✅ Working
RLDAILY Resets every 24 real-life hours ✅ Working
RLWEEKLY Resets every 7 real-life days ✅ Working
RLCUSTOM Custom real-time interval ✅ Working

Stock UI Features - COMPLETE ✅

Feature Status Notes
Stock count per item ✅ Shows to right of output slot
Out of stock indicator ✅ Dark overlay + red count
Reset timer countdown ✅ Real-time client-side countdown in top-right
"Reopen Trader" message ✅ Shows when countdown reaches 0
Admin stock configuration ✅ SubGuiNpcTraderStock
Per-slot stock limits ✅ SubGuiNpcTraderStockSlots
Reset stock button ✅ With confirmation dialog
Reset cooldown button ✅ With confirmation dialog

2.2 Trader Currency Support - COMPLETE ✅

Trades can require BOTH items AND currency (additive costs). Uses PlayerCurrencyData which auto-delegates to Vault when enabled.

Trade Entry Structure

Each trade slot can have:

  • Sold Item - What the player receives ✅
  • Currency 1 - First item cost (existing) ✅
  • Currency 2 - Second item cost (existing) ✅
  • Currency Cost - CNPC+ Currency / Vault cost ✅ NEW

Implementation Details

  • Currency cost stored as long[] currencyCost[18] in RoleTrader
  • Uses data.tradeData.getBalance() and data.tradeData.withdraw()
  • Automatically uses Vault when ConfigMarket.UseVault is enabled
  • NBT serialization for persistence ✅

2.3 Player Trader GUI - COMPLETE ✅

Display Features

Element Position Status
"Trader" label Top-left ✅
Reset countdown Top-right ✅ Real-time ticking
Stock count Right of each trade ✅ Green/Red
Player balance Bottom-right ✅
Status message Bottom-left ✅ On hover

2.4 Multi-Player Sync - COMPLETE ✅

MarketRegistry provides linked market synchronization across all NPCs sharing the same market.


2.5 Scripting API - COMPLETE ✅

Full API available via IRoleTrader interface.


3. Auction House System

Status: COMPLETE ✅

3.1 Architecture Overview

┌─────────────────────────────────────────────────────────────────┐
│                     AuctionController                            │
│  - Manages auction listings with player indices                  │
│  - Handles listing/bidding/buyout logic                          │
│  - Uses ConcurrentHashMap for thread-safety (no locks)           │
│  - Async saves on CNPC+ thread every 30 seconds                  │
│  - 30-second update cycle for processing ended auctions          │
└─────────────────────────────────────────────────────────────────┘
                              │
              Uses PlayerCurrencyData (Vault-aware)
                              │
┌─────────────────────────────────────────────────────────────────┐
│                     PlayerTradeData                              │
│  - Combined currency + auction claims (shared across profiles)   │
│  - Currency: Vault integration with local fallback               │
│  - Claims: Thread-safe CopyOnWriteArrayList for async additions  │
│  - Expired claims processed on login                             │
│  - Notifications sent immediately to online players              │
└─────────────────────────────────────────────────────────────────┘

3.2 Vault Integration

The Auction system uses PlayerCurrencyData for all currency operations:

  • AuctionController.createListing() → currencyData.withdraw(fee)
  • AuctionController.placeBid() → currencyData.withdraw(bidAmount)
  • AuctionController.buyout() → currencyData.withdraw(buyoutPrice)
  • AuctionController.claimCurrency() → currencyData.deposit(amount)

When Vault is enabled (ConfigMarket.UseVault = true):

  • All operations automatically use Vault economy
  • No code changes required - PlayerCurrencyData handles delegation

3.3 GUI Structure

GuiAuctionInterface (Base GUI - opened via Auctioneer NPC)
    │
    ├── GuiAuctionListing (Browse auctions - PAGE_LISTINGS)
    │   - 9x5 grid of auction items
    │   - Filter button with tooltip showing current settings
    │   - Click item → Opens GuiAuctionBidding
    │   - Pagination with up/down arrows
    │
    ├── GuiAuctionSell (Create new listing - PAGE_SELL)
    │   - Sell slot for item to auction (cloned from inventory)
    │   - Click inventory: left=add stack, right=add 1
    │   - Click sell slot: left=clear, right=remove 1
    │   - Starting price + buyout price text fields
    │   - Allow Buyout toggle button
    │   - Listing fee display
    │   - Confirm button with coin icon
    │
    ├── GuiAuctionTrades (My Trades - PAGE_CLAIMS)
    │   - 9x5 grid showing: active listings, active bids, claims
    │   - Blue tint: active listings/bids
    │   - Green tint: claimable items
    │   - Red tint: refunds
    │   - Confirmation system for cancel/claim operations
    │
    ├── GuiAuctionBidding (View listing details)
    │   - Item display slot
    │   - Auction info (seller, price, time, bids)
    │   - Bid button → SubGuiAuctionBid
    │   - Buy Now button → SubGuiAuctionBuyNow
    │   - Own listings: buttons hidden, view-only
    │
    ├── SubGuiAuctionBid (Bid confirmation popup)
    │   - Shows minimum bid, player balance
    │   - Bid amount input field
    │   - Place Bid / Cancel buttons
    │
    ├── SubGuiAuctionBuyNow (Buyout confirmation popup)
    │   - Shows buyout price, player balance
    │   - Yes / Cancel buttons
    │
    └── SubGuiAuctionSearch (Filter popup)
        - Search text input
        - Apply/Cancel buttons

3.4 Client Config Sync

The client uses AuctionClientConfig to cache server settings:

  • Synced via LoginPacket on player join
  • Client never uses ConfigMarket directly for display
  • Ensures server authority over fees, currency name, etc.
// Server sends config in LoginPacket
AuctionClientConfig.writeToNBT(compound);  // Server side

// Client receives and caches
AuctionClientConfig.readFromNBT(compound);  // Client side

// Client GUI uses cached values
AuctionClientConfig.getListingFee();
AuctionClientConfig.getCurrencyName();
AuctionClientConfig.getMinBidIncrement();

3.5 Data Structures

AuctionListing

public class AuctionListing {
    String id;                 // Unique listing ID (UUID-based)
    UUID sellerUUID;           // Seller's UUID
    String sellerName;         // Seller's display name
    ItemStack item;            // Item being sold
    long startingPrice;        // Minimum starting bid
    long buyoutPrice;          // Instant buy price (0 = no buyout)
    long currentBid;           // Current highest bid
    UUID highBidderUUID;       // Current high bidder (null if no bids)
    String highBidderName;     // High bidder display name
    int bidCount;              // Number of bids placed
    long createdTime;          // When listing was created
    long endTime;              // When auction ends
    EnumAuctionStatus status;  // ACTIVE, ENDED, CANCELLED, CLAIMED
}

AuctionClaim

public class AuctionClaim {
    String id;                 // Unique claim ID
    UUID playerUUID;           // Player who can claim
    String listingId;          // Related auction listing
    EnumClaimType type;        // ITEM, CURRENCY, REFUND
    ItemStack item;            // Item to claim (if type = ITEM)
    long currency;             // Currency to claim (if type = CURRENCY/REFUND)
    long createdTime;          // When claim was created
    boolean claimed;           // Whether claimed
}

3.6 Security Features

All actions are validated server-side:

Check Location Description
Own item bid prevention placeBid() listing.isSeller(playerUUID) check
Own item buyout prevention buyout() listing.isSeller(playerUUID) check
Auction expiry check placeBid()/buyout() Double-check inside write lock
Currency validation All actions Verify balance before operations
Claim ownership claimItem()/claimCurrency() claim.isForPlayer(playerUUID) check
Blacklist check createListing() AuctionBlacklist.isBlacklistedForPlayer() check
Bound item check createListing() Auto-blocks Soulbound/Profile-Slotbound items

3.7 Snipe Protection

When a bid is placed with less than SnipeProtectionMinutes remaining:

  • Extend the auction end time TO SnipeProtectionMinutes from now
  • Never extend beyond SnipeProtectionMinutes
  • Default: 2 minutes

Example: Auction ends in 30 seconds, someone bids → Timer resets to 2:00


3.8 Item Blacklist System

Prevents specific items from being listed on the auction house.

Blacklist Types

Type Description Example
Items Block specific items by registry name minecraft:diamond_sword
Wildcards Block items matching pattern minecraft:diamond*
Mods Block all items from a mod customnpcs
NBT Tags Block items with specific NBT ench (enchanted items)

Auto-Blocked Items (Always Blocked)

These items are always blocked regardless of blacklist settings:

  • Soulbound Items - Items with cnpc_soulbind requirement
  • Profile-Slotbound Items - Items with cnpc_profile_slot requirement

The system checks for these under RPGCore/Requirements in the item's NBT.

Bypass Permission

Players with OP status or the customnpcs.auction.blacklist.bypass permission can list blacklisted items.

Configuration

Market.Auction.Blacklist:
  Enabled: true
  BlacklistedItems: ["minecraft:barrier", "minecraft:command_block*"]
  BlacklistedMods: []
  BlacklistedNBTTags: []

Commands

Command Description
/cnpc auction blacklist add <item|mod|nbt> <value> Add to blacklist (runtime only)
/cnpc auction blacklist remove <item|mod|nbt> <value> Remove from blacklist (runtime only)
/cnpc auction blacklist list [item|mod|nbt] List blacklisted entries
/cnpc auction blacklist reload Reload blacklist from config
/cnpc auction blacklist check Check if held item is blacklisted

4. AuctionController Performance & Thread Safety

4.1 Threading Model

┌─────────────────────────────────────────────────────────────────┐
│                    AuctionController                              │
│                                                                   │
│  ┌─────────────────────┐  ┌─────────────────┐  ┌───────────────┐ │
│  │ ConcurrentHashMap   │  │ AtomicBoolean   │  │ CNPC+ Thread  │ │
│  │ (listings, indices) │  │ dirty, saving   │  │ (async saves) │ │
│  └─────────────────────┘  └─────────────────┘  └───────────────┘ │
│                                                                   │
│  All operations use ConcurrentHashMap - no explicit locking       │
│  Minecraft is single-threaded for gameplay - inherent safety      │
│  Async saves snapshot data before writing to disk                 │
└─────────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────────┐
│                    PlayerTradeData                                │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ Currency: long balance (or Vault delegation)                 │ │
│  │ Claims: CopyOnWriteArrayList<AuctionClaim>                   │ │
│  │ - Thread-safe for concurrent read/write                      │ │
│  │ - Claims can be added from CNPC+ thread for offline players  │ │
│  │ - Stored in PlayerData (persisted with player, not auctions) │ │
│  └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

4.2 Player Indices for O(1) Lookups

Index Type Purpose
playerListingIds Map<UUID, Set<String>> Active listings by seller
playerBidIds Map<UUID, Set<String>> Listings where player has active bid

Claims are now stored in PlayerData:

  • PlayerTradeData.claims - CopyOnWriteArrayList per player
  • Accessed via PlayerData.get(player).tradeData
  • Shared across all profile slots (combined with currency)

Performance Impact:

  • getPlayerListingCount(): O(n) → O(1)
  • getPlayerActiveListings(): O(n) → O(k) where k = player's listings
  • getPlayerActiveBids(): O(n) → O(k)
  • getPlayerClaims(): Direct access to player's claims list

4.3 Update Intervals

Operation Interval Rationale
Process ended auctions 30 seconds (600 ticks) Reduces server load
Save auction data 30 seconds (600 ticks) Batches writes, reduces I/O
Process expired claims On player login Per-player, not global tick

4.4 Data Safety

  1. Currency Deduction - Withdraw before updating listing
  2. Previous Bidder Refund - Store info before modification
  3. Concurrent Saves - AtomicBoolean prevents duplicates
  4. Offline Player Claims - Loaded async on CNPC+ thread, saved to PlayerData
  5. Claim Migration - Old claims in auction.dat migrated to PlayerData on load

4.5 Server Shutdown Handling

On FMLServerStoppedEvent:

  1. AuctionController.save() called synchronously
  2. Uses CNPC+ thread (single-threaded executor)
  3. All pending saves complete before shutdown

5. File Structure

New Files Created

constants/
  EnumAuctionStatus.java     ✅
  EnumAuctionSort.java       ✅
  EnumClaimType.java         ✅
  EnumNotificationType.java  ✅

controllers/
  AuctionController.java     ✅ (with threading, indices, Vault support)
  AuctionConfigSync.java     ✅ (server-side config sync utility)

controllers/data/
  AuctionListing.java        ✅
  AuctionClaim.java          ✅
  AuctionFilter.java         ✅
  AuctionBlacklist.java      ✅ (item blacklist checking + bypass)
  PlayerTradeData.java       ✅ (currency + claims storage per player)

roles/
  RoleAuctioneer.java        ✅

containers/
  ContainerAuction.java         ✅
  ContainerAuctionListing.java  ✅
  ContainerAuctionBidding.java  ✅
  ContainerAuctionTrades.java   ✅
  ContainerAuctionSell.java     ✅
  InventoryAuctionDisplay.java  ✅
  SlotAuctionDisplay.java       ✅

client/
  AuctionClientConfig.java      ✅ (client-side config cache)

client/gui/player/
  GuiAuctionInterface.java      ✅
  GuiAuctionListing.java        ✅
  GuiAuctionSell.java           ✅
  GuiAuctionTrades.java         ✅
  GuiAuctionBidding.java        ✅
  SubGuiAuctionSearch.java      ✅
  SubGuiAuctionBid.java         ✅
  SubGuiAuctionBuyNow.java      ✅
  AuctionTooltipHandler.java    ✅

client/gui/util/
  GuiAuctionNavButton.java      ✅

network/packets/player/
  AuctionActionPacket.java      ✅

New Commands

command/
  AuctionCommand.java                    ✅ /cnpc auction with list, view, open, blacklist
  command/auction/
    BlacklistSubCommand.java             ✅ /cnpc auction blacklist subcommands

Files Modified

CustomNpcs.java              ✅ Initialize AuctionController, save on shutdown
EnumRoleType.java            ✅ Added Auctioneer
EnumGuiType.java             ✅ Added PlayerAuction, PlayerAuctionSell, PlayerAuctionTrades, PlayerAuctionBidding
EnumPlayerPacket.java        ✅ Added AuctionData, AuctionAction
CommonProxy.java             ✅ Handle auction container types
ClientProxy.java             ✅ Handle auction GUI types
DataAdvanced.java            ✅ Handle Auctioneer role
ConfigMarket.java            ✅ Added Auction section
LoginPacket.java             ✅ Sync auction config to client
PlayerData.java              ✅ Added tradeData field (currency + claims, shared across profiles)
en_US.lang                   ✅ Added auction lang keys

6. Configuration

ConfigMarket.java Structure

// =========================================
// Currency (Market.Currency)
// =========================================
public static boolean UseVault = false;          // Use Vault economy
public static String CurrencyName = "Coins";     // Display name
public static long StartingBalance = 0;          // New player balance
public static long MaxBalance = Long.MAX_VALUE;  // Balance cap

// =========================================
// Auction (Market.Auction)
// =========================================
public static final int MAX_TRADE_SLOTS = 45;    // 9x5 grid maximum
public static final int MIN_TRADE_SLOTS = 1;     // Minimum allowed

public static boolean AuctionEnabled = true;
public static int AuctionDurationHours = 24;     // Auction length (hours)
public static long ListingFee = 10;              // Fee to create listing
public static long MinimumListingPrice = 1;      // Minimum starting price
public static double SalesTaxPercent = 0.05;     // 5% tax on sales
public static int DefaultMaxTrades = 8;          // Per player (listings + bids + claims)
public static int SnipeProtectionMinutes = 2;    // Anti-snipe timer
public static int ClaimExpirationDays = 20;      // Days before unclaimed deleted
public static double MinBidIncrementPercent = 0.05; // 5% minimum bid increase

// =========================================
// Auction Logging
// =========================================
public static boolean AuctionLoggingEnabled = false;
public static boolean LogAuctionCreated = true;
public static boolean LogAuctionBid = true;
public static boolean LogAuctionBuyout = true;
public static boolean LogAuctionSold = true;
public static boolean LogAuctionExpired = true;
public static boolean LogAuctionCancelled = true;
public static boolean LogAuctionClaimed = true;

// =========================================
// Auction Blacklist (Market.Auction.Blacklist)
// =========================================
public static boolean BlacklistEnabled = true;
public static String[] BlacklistedItems = {};    // Registry names (supports wildcards)
public static String[] BlacklistedMods = {};     // Mod IDs to block entirely
public static String[] BlacklistedNBTTags = {};  // NBT tag keys to block

Auction Permissions

Permission Description
customnpcs.auction.trades.* Unlimited trade slots (up to 45)
customnpcs.auction.trades.X Exactly X trade slots (where X is 1-45)
customnpcs.auction.blacklist.bypass Bypass item blacklist restrictions

Trade Slot Permissions:

  • Default is 8 trade slots
  • Permissions only increase the limit (permissions below 8 are ignored)
  • Maximum is capped at 45 (9x5 grid)
  • Trade slots = Active Listings + Active Bids + Pending Claims

Blacklist Bypass:

  • OP players or those with customnpcs.auction.blacklist.bypass can list blacklisted items
  • Soulbound and Profile-Slotbound items are always blocked (no bypass)

7. Commands

/cnpc auction Command

Allows interaction with the Auction House without needing an Auctioneer NPC.

Subcommand Usage Permission Description
list /cnpc auction list [page] OP View active auctions in chat
view /cnpc auction view <player> OP View a player's auction activity
open /cnpc auction open Any Opens the Auction House GUI

Examples:

/cnpc auction list           - Show first page of active auctions
/cnpc auction list 2         - Show page 2 of auctions
/cnpc auction view Steve     - Show Steve's listings, bids, and claims
/cnpc auction open           - Open the full Auction House GUI

/cnpc auction blacklist Command

Manage the auction item blacklist (runtime changes, not persisted to config).

Subcommand Usage Permission Description
add /cnpc auction blacklist add <item|mod|nbt> <value> OP Add to blacklist
remove /cnpc auction blacklist remove <item|mod|nbt> <value> OP Remove from blacklist
list /cnpc auction blacklist list [item|mod|nbt] OP List blacklisted entries
reload /cnpc auction blacklist reload OP Reload from config
check /cnpc auction blacklist check Any Check if held item is blacklisted

Examples:

/cnpc auction blacklist add item minecraft:diamond_sword
/cnpc auction blacklist add item minecraft:diamond*    (wildcard)
/cnpc auction blacklist add mod industrialcraft2
/cnpc auction blacklist add nbt ench
/cnpc auction blacklist remove item minecraft:diamond_sword
/cnpc auction blacklist list item
/cnpc auction blacklist check                          (checks held item)

8. Implementation Status

Phase 1: Currency System - COMPLETE ✅

Phase 2: Trader Enhancements - COMPLETE ✅

Phase 3: Auction Core - COMPLETE ✅

Phase 4: Auction GUI - COMPLETE ✅

Phase 5: Auction Network - COMPLETE ✅

Phase 6: Performance & Safety - COMPLETE ✅

  1. Threading model with ReentrantReadWriteLock
  2. Player indices for O(1) lookups
  3. 20-second update cycle
  4. Async saves on CNPC+ thread
  5. Race condition prevention
  6. Server shutdown handling
  7. Own listing view (buttons hidden)
  8. Server-side security checks

Remaining Work

  • GuiManageAuction (Admin GUI) - Admin interface to view all auctions, cancel listings, manage claims
  • Additional testing

Implemented Since Initial Plan

  • /auction Command - Console/player command with subcommands:
    • /auction list [page] - View active auctions from command line
    • /auction view <player> - View a player's auction activity (listings, bids, claims)
    • /auction open - Open Auction House GUI without needing an Auctioneer NPC
  • Permission system integration - Per-player trade slot limits via customnpcs.auction.trades.X permissions
    • Default: 8 trade slots
    • Maximum: 45 (9x5 grid)
    • Synced to client when viewing My Trades
    • Cached on login for performance
  • Minimum Listing Price - Configurable minimum starting price (default: 1)
  • Buyout enabled by default - Buyout toggle is ON by default when creating listings
  • Search by seller - Filter can now search by item name OR seller name
  • Rebid prevention - Players cannot rebid on auctions where they're already the highest bidder
  • Buyout price difference - When buying out an auction you're bidding on, only pay the difference
  • Immediate claim cleanup - Claims are removed from storage immediately when claimed
  • Listing cleanup - Ended listings are removed when all related claims are processed
  • Live notifications - Notifications sent immediately to online players instead of queued
  • Login claim summary - Shows detailed claim summary on login (X items and Y currency to claim)
  • PlayerTradeData - Merged currency + claims into single class (shared across profiles)
  • No locking system - Pure ConcurrentHashMap for better performance
  • 30-second intervals - Combined process/save cycle for simplicity
  • Async offline player claims - Claims added to offline players via CNPC+ thread
  • Claim migration - Old claims in auction.dat automatically migrated to PlayerData
  • Item Blacklist System - Block items by registry name, mod, NBT tag, or wildcard pattern
    • Auto-blocks Soulbound and Profile-Slotbound items (checks RPGCore/Requirements)
    • Per-player bypass via customnpcs.auction.blacklist.bypass permission
    • Runtime add/remove commands (not persisted to config)
    • Check command to test held item

9. Design Decisions

Decision Choice Rationale
Claims Storage In PlayerData, not auction.dat Claims persist with player, reduces auction.dat size, allows offline claim addition
Thread Safety ConcurrentHashMap (no locks) Minecraft is single-threaded for gameplay; locks add overhead without benefit
Vault Integration Via PlayerCurrencyData Single point of delegation, reused by Trader & Auction
Update Interval 30 seconds Performance vs responsiveness tradeoff
Player Indices ConcurrentHashMap + Sets O(1) lookups, thread-safe
Async Saves CNPC+ Thread Doesn't block server tick
Offline Claims Load PlayerData async, add claim, save Claims can be added to offline players without blocking
Config Sync LoginPacket → AuctionClientConfig Client never accesses server config directly
Item Blacklist Static utility class Simple, fast checks without instantiation; auto-blocks bound items
Bound Item Detection Check RPGCore/Requirements NBT path Uses AttributeItemUtil constants for consistency

10. Future Considerations (Not in 1.11)

  • Category-based filtering (by item type, mod, etc.)
  • Auction history/statistics tracking
  • Auction house tax sink (currency removed from economy)
  • Reserve prices (hidden minimum price)
  • Private auctions (invite-only)
  • Watchlist/favorites system
  • Price history graphs