# RSC Revolution Market System - Technical Specification ## Executive Summary The RSC Revolution Market System is a comprehensive auction house implementation that enables players to buy and sell items through a centralized marketplace. The system supports both buy orders and sell orders, with automatic expiration, collection mechanisms, and full transaction history tracking. ## Architecture Overview ### Core Components ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Client UI │◄──►│ Market Handler │◄──►│ Market Service │ │ (MarketInterface)│ │ (MarketHandlers)│ │ (MarketService) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ ┌─────────────────┐ │ Task System │ │ Market Database │ │ (8 Tasks) │ │(MarketDatabase) │ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ MySQL Database │ │ pk_market_active, pk_market_inactive, │ │ pk_market_collectable, pk_market_sales │ └─────────────────────────────────────────┘ ``` ## Database Schema ### Table: `pk_market_active` Active market listings currently available for trading. ```sql CREATE TABLE pk_market_active ( auctionID INT AUTO_INCREMENT PRIMARY KEY, item_id INT NOT NULL, item_initial_amount INT NOT NULL, item_amount_left INT NOT NULL, price_each INT NOT NULL, player_id INT NOT NULL, listing_type TINYINT NOT NULL, -- 0=sell order, 1=buy order time BIGINT NOT NULL, deadman TINYINT DEFAULT 0, FOREIGN KEY (player_id) REFERENCES pk_players(id) ); ``` ### Table: `pk_market_inactive` Historical record of expired/completed/cancelled listings. ```sql CREATE TABLE pk_market_inactive ( auction_id INT PRIMARY KEY, player_id INT NOT NULL, item_id INT NOT NULL, item_initial_amount INT NOT NULL, item_amount INT NOT NULL, price_each INT NOT NULL, remove_type TINYINT NOT NULL, -- 0=sold out, 1=expired, 2=moderator, 3=cancelled listing_type TINYINT NOT NULL, time BIGINT NOT NULL, deadman TINYINT DEFAULT 0 ); ``` ### Table: `pk_market_collectable` Items and coins waiting to be collected by players. ```sql CREATE TABLE pk_market_collectable ( claim_id INT AUTO_INCREMENT PRIMARY KEY, auction_id INT NOT NULL, sale_id INT DEFAULT -1, player_id INT NOT NULL, item_id INT NOT NULL, item_amount INT NOT NULL, time BIGINT NOT NULL, type TINYINT NOT NULL -- 0=return, 1=purchase, 2=profit, 3=return_mod ); ``` ### Table: `pk_market_sales` Transaction records for completed sales. ```sql CREATE TABLE pk_market_sales ( sale_id INT AUTO_INCREMENT PRIMARY KEY, auction_id INT NOT NULL, player_id INT NOT NULL, -- buyer's ID amount INT NOT NULL, time BIGINT NOT NULL ); ``` ### Table: `pk_market_collected` Successfully collected items (audit trail). ```sql CREATE TABLE pk_market_collected ( claim_id INT PRIMARY KEY, auction_id INT NOT NULL, player_id INT NOT NULL, item_id INT NOT NULL, item_amount INT NOT NULL, time BIGINT NOT NULL, claim_time BIGINT NOT NULL, sale_id INT DEFAULT -1, type TINYINT NOT NULL ); ``` ## System Initialization and Lifecycle ### Server Startup Process 1. **Service Registration** (`Server.java:49`) ```java private final MarketService market = new MarketService(); ``` 2. **Service Initialization** (`MarketService.java:29-35`) ```java public MarketService() { super(50); // 50ms tick rate marketItems = new ArrayList<>(); marketTaskQueue = new LinkedBlockingQueue<>(); refreshRequestTasks = new LinkedBlockingQueue<>(); database = new MarketDatabase(); } ``` 3. **Cache Loading** - Market items are loaded from database on-demand - Cache refresh occurs when item count changes - Items are cached in memory as `ArrayList` ### Runtime Processing Loop The MarketService runs on a 50ms tick cycle (`MarketService.java:143-150`): ```java @Override public void process() { if (System.currentTimeMillis() - lastCleanUp > 60000) { checkAndRemoveExpiredItems(); // Every 60 seconds } processAuctionTasks(); // Process queued tasks processUpdateAuctionItemCache(); // Update cache if needed processRefreshRequests(); // Handle UI refresh requests } ``` ### Expiration Management **Expiration Logic** (`MarketItem.java:4,30-40,62-64`): - **Time Limit**: 48 hours (172,800 seconds) - **Check Frequency**: Every 60 seconds - **Expiration Action**: Move to inactive, create collectable return item ```java private static final int TIME_LIMIT = (60 * 60 * 24) * 2; // 48 hours public boolean hasExpired() { return getHoursLeft() <= 0; } public int getHoursLeft() { int expireDate = (int) (time + TIME_LIMIT); int curTime = (int) (System.currentTimeMillis() / 1000); int timeDiff = (int) (expireDate - curTime); return timeDiff < 0 ? 0 : timeDiff / 60 / 60; } ``` ## User Flow and Interactions ### Market Access Flow 1. **Initial Access** (`Auctioneer.java`) - Player talks to Auctioneer NPC (ID: 811) - Bank PIN verification required - Iron Man restriction check - Market interface opens 2. **Interface Actions** (`MarketHandlers.java:15-109`) | Action | Type | Description | Handler | |--------|------|-------------|---------| | 0 | Buy/Sell | Execute transaction | `BuySellMarketTask` | | 1 | Post | Create new listing | `CreateListingMarketTask` | | 2 | Cancel | Cancel own listing | `CancelListingMarketTask` | | 3 | Refresh | Update market view | UI refresh (5s cooldown) | | 4 | Close | Close interface | Set accessing flag false | | 5 | Mod Delete | Moderator deletion | `DeleteListingMarketTask` | ### Listing Creation Process **Sell Order Creation** (`CreateListingMarketTask.java`): 1. Validate player has items in inventory 2. Check listing limits (10 buy orders max per player) 3. Verify item is tradeable (not untradeable) 4. Remove items from inventory 5. Create database record in `pk_market_active` 6. Add to cache 7. Refresh player's market view **Buy Order Creation**: 1. Validate player has coins 2. Check listing limits 3. Remove coins from inventory 4. Create database record with `listing_type = 1` 5. Add to cache ### Transaction Processing **Buy Transaction Flow** (`BuySellMarketTask.java:111-201`): 1. Validate auction item exists and available 2. Check deadman mode compatibility 3. Validate buyer has sufficient coins 4. Attempt item placement (inventory → bank if full) 5. Remove coins from buyer 6. Create sale record in `pk_market_sales` 7. Create collectable profit item for seller 8. Update item amount or move to inactive if sold out 9. Notify seller of sale **Sell Transaction Flow** (`BuySellMarketTask.java:43-109`): 1. Validate buy order exists 2. Check seller has required items (noted or regular) 3. Remove items from seller inventory 4. Create sale record 5. Create collectable purchase item for buyer 6. Add coins to seller inventory 7. Update buy order or complete if filled ### Collection System **Collectable Item Types** (`CollectableItem.java`): - **RETURN (0)**: Expired/cancelled items returned to owner - **PURCHASE (1)**: Items bought by player waiting collection - **PROFIT (2)**: Coins from sales waiting collection - **RETURN_MOD (3)**: Items returned due to moderator action **Collection Process** (`CollectItemsMarketTask.java`): 1. Query `pk_market_collectable` for player's items 2. Validate inventory/bank space 3. Add items/coins to player 4. Move record to `pk_market_collected` 5. Remove from `pk_market_collectable` ## Security and Restrictions ### Access Control - **Iron Man Restriction**: Cannot access market at all - **Bank PIN**: Required for market access via Auctioneer - **Server Shutdown**: Market disabled during shutdown countdown - **Deadman Separation**: Separate economies (deadman flag) ### Anti-Abuse Measures - **Refresh Rate Limiting**: 5-second cooldown on market refresh - **Self-Trading Prevention**: Cannot buy own items - **Listing Limits**: 10 buy orders maximum per player - **Item Validation**: Untradeable items blocked - **Bronze Man Restrictions**: 6-hour waiting period, unlock requirements ### Data Integrity - **Transaction Atomicity**: Database operations wrapped in transactions - **Rollback on Failure**: Items/coins restored if database operations fail - **Audit Trail**: Complete transaction history in multiple tables - **Expiration Safety**: Items automatically returned after 48 hours ## Performance Considerations ### Caching Strategy - **In-Memory Cache**: All active listings cached in `ArrayList` - **Lazy Loading**: Cache updated only when item count changes - **Cache Invalidation**: Immediate updates for item quantity changes ### Database Optimization - **Prepared Statements**: All queries use prepared statements - **Connection Pooling**: Uses HikariCP connection pool - **Indexed Queries**: Primary keys and foreign keys properly indexed - **Batch Operations**: Expired items processed in batches ### Scalability Features - **Asynchronous Processing**: All market operations queued and processed asynchronously - **Service Architecture**: Market service runs independently on 50ms ticks - **Database Separation**: Market tables isolated from game data - **Task Queue System**: Non-blocking task processing ## Configuration and Monitoring ### Configuration Parameters - **Tick Rate**: 50ms (MarketService extends Service with 50ms interval) - **Expiration Time**: 48 hours (configurable in MarketItem.TIME_LIMIT) - **Cleanup Frequency**: 60 seconds (configurable in MarketService.process()) - **Buy Order Limit**: 10 per player (hardcoded in CreateListingMarketTask) ### Monitoring and Logging - **SLF4J Logging**: Comprehensive error logging in all components - **Exception Handling**: All database operations wrapped in try-catch - **Transaction Logging**: Sale records maintained in pk_market_sales - **Audit Trail**: Complete history in pk_market_collected ## API Reference for AI Agents ### Key Methods **MarketService** (`com.rscr.server.market.MarketService`): ```java public void addMarketTask(MarketTask marketTask) public void addRequestOpenAuctionHouseTask(Player player) public ArrayList getMarketItems() public int getAuctionCount(Player owner, int type) ``` **MarketDatabase** (`com.rscr.server.market.MarketDatabase`): ```java public boolean add(MarketItem item) public ArrayList getAuctionItems() public boolean updateAmountLeft(MarketItem item) public boolean setInactive(MarketItem item, int remove_type) public int addSaleInfo(int auctionID, int amount, Player playerBuyer) ``` **MarketItem** (`com.rscr.server.market.MarketItem`): ```java public boolean hasExpired() public int getHoursLeft() public int getType() // 0=sell order, 1=buy order ``` ### Task System Classes All tasks extend `MarketTask` and implement `doTask()` method: - `OpenMarketTask`: Opens market interface - `CreateListingMarketTask`: Creates new listings - `BuySellMarketTask`: Processes transactions - `CancelListingMarketTask`: Cancels listings - `DeleteListingMarketTask`: Moderator deletions - `CollectItemsMarketTask`: Handles item collection - `ViewHistoryMarketTask`: Shows transaction history - `CollectableNotificationMarketTask`: Manages notifications ## Error Handling and Edge Cases ### Common Error Scenarios 1. **Database Connection Failures**: Operations fail gracefully, items restored 2. **Inventory Full**: Items placed in bank, fallback to collectable system 3. **Concurrent Modifications**: Database constraints prevent duplicate sales 4. **Server Shutdown**: Market disabled, ongoing operations completed 5. **Item ID Changes**: System handles both noted and regular item IDs ### Recovery Mechanisms - **Automatic Rollback**: Failed transactions restore player state - **Expiration Safety Net**: Items automatically returned after timeout - **Audit Trail**: Complete transaction history for debugging - **Graceful Degradation**: System continues operating with reduced functionality This specification provides complete technical understanding of the RSC Revolution Market System for AI agents to effectively work with, modify, or extend the marketplace functionality.