315 lines
9.3 KiB
Markdown
315 lines
9.3 KiB
Markdown
# Collections System
|
|
|
|
The collections system provides comprehensive achievement-based item collection functionality for EverQuest II server emulation, converted from the original C++ EQ2EMu implementation.
|
|
|
|
## Overview
|
|
|
|
The collections system allows players to find specific items scattered throughout the game world and combine them into collections for rewards. When players complete a collection by finding all required items, they receive rewards such as experience, coins, items, or a choice of selectable items.
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
|
|
**Collection** - Individual collection with required items, rewards, and completion tracking
|
|
**MasterCollectionList** - Registry of all available collections in the game
|
|
**PlayerCollectionList** - Per-player collection progress and completion tracking
|
|
**CollectionManager** - High-level collection system coordinator
|
|
**CollectionService** - Service layer for game integration and client communication
|
|
|
|
### Key Features
|
|
|
|
- **Item-Based Collections**: Players find specific items to complete collections
|
|
- **Multiple Reward Types**: Coins, experience points, fixed items, and selectable items
|
|
- **Progress Tracking**: Real-time tracking of collection completion progress
|
|
- **Category Organization**: Collections organized by categories for easy browsing
|
|
- **Level Restrictions**: Collections appropriate for different player levels
|
|
- **Thread Safety**: All operations use proper Go concurrency patterns
|
|
- **Database Persistence**: Player progress saved automatically
|
|
|
|
## Collection Structure
|
|
|
|
### Collection Data
|
|
- **ID**: Unique collection identifier
|
|
- **Name**: Display name for the collection
|
|
- **Category**: Organizational category (e.g., "Artifacts", "Shinies")
|
|
- **Level**: Recommended level for the collection
|
|
- **Items**: List of required items with index positions
|
|
- **Rewards**: Coins, XP, items, and selectable items
|
|
|
|
### Item States
|
|
- **Not Found** (0): Player hasn't found this item yet
|
|
- **Found** (1): Player has found and added this item to the collection
|
|
|
|
### Collection States
|
|
- **Incomplete**: Not all required items have been found
|
|
- **Ready to Turn In**: All items found but not yet completed
|
|
- **Completed**: Collection has been turned in and rewards claimed
|
|
|
|
## Database Schema
|
|
|
|
### Collections Table
|
|
```sql
|
|
CREATE TABLE collections (
|
|
id INTEGER PRIMARY KEY,
|
|
collection_name TEXT NOT NULL,
|
|
collection_category TEXT NOT NULL DEFAULT '',
|
|
level INTEGER NOT NULL DEFAULT 0,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
### Collection Details Table
|
|
```sql
|
|
CREATE TABLE collection_details (
|
|
collection_id INTEGER NOT NULL,
|
|
item_id INTEGER NOT NULL,
|
|
item_index INTEGER NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (collection_id, item_id),
|
|
FOREIGN KEY (collection_id) REFERENCES collections(id) ON DELETE CASCADE
|
|
);
|
|
```
|
|
|
|
### Collection Rewards Table
|
|
```sql
|
|
CREATE TABLE collection_rewards (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
collection_id INTEGER NOT NULL,
|
|
reward_type TEXT NOT NULL, -- 'Item', 'Selectable', 'Coin', 'XP'
|
|
reward_value TEXT NOT NULL,
|
|
reward_quantity INTEGER NOT NULL DEFAULT 1,
|
|
FOREIGN KEY (collection_id) REFERENCES collections(id) ON DELETE CASCADE
|
|
);
|
|
```
|
|
|
|
### Player Collections Table
|
|
```sql
|
|
CREATE TABLE character_collections (
|
|
char_id INTEGER NOT NULL,
|
|
collection_id INTEGER NOT NULL,
|
|
completed INTEGER NOT NULL DEFAULT 0,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (char_id, collection_id),
|
|
FOREIGN KEY (collection_id) REFERENCES collections(id) ON DELETE CASCADE
|
|
);
|
|
```
|
|
|
|
### Player Collection Items Table
|
|
```sql
|
|
CREATE TABLE character_collection_items (
|
|
char_id INTEGER NOT NULL,
|
|
collection_id INTEGER NOT NULL,
|
|
collection_item_id INTEGER NOT NULL,
|
|
found_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (char_id, collection_id, collection_item_id),
|
|
FOREIGN KEY (char_id, collection_id) REFERENCES character_collections(char_id, collection_id) ON DELETE CASCADE
|
|
);
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### System Initialization
|
|
|
|
```go
|
|
// Initialize collection service
|
|
database := NewDatabaseCollectionManager(db)
|
|
itemLookup := NewItemLookupService()
|
|
clientManager := NewClientManager()
|
|
|
|
service := NewCollectionService(database, itemLookup, clientManager)
|
|
err := service.Initialize(ctx)
|
|
```
|
|
|
|
### Player Operations
|
|
|
|
```go
|
|
// Load player collections when they log in
|
|
err := service.LoadPlayerCollections(ctx, characterID)
|
|
|
|
// Process when player finds an item
|
|
err := service.ProcessItemFound(characterID, itemID)
|
|
|
|
// Complete a collection
|
|
rewardProvider := NewRewardProvider()
|
|
err := service.CompleteCollection(characterID, collectionID, rewardProvider)
|
|
|
|
// Get player's collection progress
|
|
progress, err := service.GetPlayerCollectionProgress(characterID)
|
|
|
|
// Unload when player logs out
|
|
err := service.UnloadPlayerCollections(ctx, characterID)
|
|
```
|
|
|
|
### Collection Management
|
|
|
|
```go
|
|
// Get all collections in a category
|
|
collections := manager.GetCollectionsByCategory("Artifacts")
|
|
|
|
// Search collections by name
|
|
collections := manager.SearchCollections("Ancient")
|
|
|
|
// Get collections appropriate for player level
|
|
collections := manager.GetAvailableCollections(playerLevel)
|
|
|
|
// Check if item is needed by any collection
|
|
needed := masterList.NeedsItem(itemID)
|
|
```
|
|
|
|
## Reward System
|
|
|
|
### Reward Types
|
|
|
|
**Coin Rewards**
|
|
```go
|
|
collection.SetRewardCoin(50000) // 5 gold
|
|
```
|
|
|
|
**Experience Rewards**
|
|
```go
|
|
collection.SetRewardXP(10000) // 10,000 XP
|
|
```
|
|
|
|
**Item Rewards** (automatically given)
|
|
```go
|
|
collection.AddRewardItem(CollectionRewardItem{
|
|
ItemID: 12345,
|
|
Quantity: 1,
|
|
})
|
|
```
|
|
|
|
**Selectable Rewards** (player chooses one)
|
|
```go
|
|
collection.AddSelectableRewardItem(CollectionRewardItem{
|
|
ItemID: 12346,
|
|
Quantity: 1,
|
|
})
|
|
```
|
|
|
|
## Integration Interfaces
|
|
|
|
### ItemLookup
|
|
Provides item information and validation for collections.
|
|
|
|
### ClientManager
|
|
Handles client communication for collection updates and lists.
|
|
|
|
### RewardProvider
|
|
Manages distribution of collection rewards to players.
|
|
|
|
### CollectionEventHandler
|
|
Handles collection-related events for logging and notifications.
|
|
|
|
## Thread Safety
|
|
|
|
All operations are thread-safe using:
|
|
- `sync.RWMutex` for collection and list operations
|
|
- Atomic updates for collection progress
|
|
- Database transactions for consistency
|
|
- Proper locking hierarchies to prevent deadlocks
|
|
|
|
## Performance Features
|
|
|
|
- **Efficient Lookups**: Hash-based collection and item lookups
|
|
- **Lazy Loading**: Player collections loaded only when needed
|
|
- **Batch Operations**: Multiple items and collections processed together
|
|
- **Connection Pooling**: Efficient database connection management
|
|
- **Caching**: Master collections cached in memory
|
|
|
|
## Event System
|
|
|
|
The collections system provides comprehensive event handling:
|
|
|
|
```go
|
|
// Item found event
|
|
OnItemFound(characterID, collectionID, itemID int32)
|
|
|
|
// Collection completed event
|
|
OnCollectionCompleted(characterID, collectionID int32)
|
|
|
|
// Rewards claimed event
|
|
OnRewardClaimed(characterID, collectionID int32, rewards []CollectionRewardItem, coin, xp int64)
|
|
```
|
|
|
|
## Statistics and Monitoring
|
|
|
|
### System Statistics
|
|
- Total collections available
|
|
- Collections per category
|
|
- Total items across all collections
|
|
- Reward distribution statistics
|
|
|
|
### Player Statistics
|
|
- Collections completed
|
|
- Collections in progress
|
|
- Items found
|
|
- Progress percentages
|
|
|
|
## Error Handling
|
|
|
|
Comprehensive error handling covers:
|
|
- Database connection failures
|
|
- Invalid collection or item IDs
|
|
- Reward distribution failures
|
|
- Concurrent access issues
|
|
- Data validation errors
|
|
|
|
## Future Enhancements
|
|
|
|
Areas marked for future implementation:
|
|
- Collection discovery mechanics
|
|
- Rare item collection bonuses
|
|
- Collection sharing and trading
|
|
- Achievement integration
|
|
- Collection leaderboards
|
|
- Seasonal collections
|
|
|
|
## File Structure
|
|
|
|
```
|
|
internal/collections/
|
|
├── README.md # This documentation
|
|
├── constants.go # Collection constants and limits
|
|
├── types.go # Core data structures
|
|
├── interfaces.go # Integration interfaces
|
|
├── collections.go # Collection implementation
|
|
├── master_list.go # Master collection registry
|
|
├── player_list.go # Player collection tracking
|
|
├── database.go # Database operations
|
|
└── manager.go # High-level collection services
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
- `eq2emu/internal/database` - Database wrapper
|
|
- Standard library: `context`, `sync`, `fmt`, `strings`, `time`
|
|
|
|
## Testing
|
|
|
|
The collections system is designed for comprehensive testing:
|
|
- Mock interfaces for all dependencies
|
|
- Unit tests for collection logic
|
|
- Integration tests with database
|
|
- Concurrent operation testing
|
|
- Performance benchmarking
|
|
|
|
## Migration from C++
|
|
|
|
Key changes from the C++ implementation:
|
|
- Go interfaces for better modularity
|
|
- Context-based operations for cancellation
|
|
- Proper error handling with wrapped errors
|
|
- Thread-safe operations using sync primitives
|
|
- Database connection pooling
|
|
- Event-driven architecture for notifications
|
|
|
|
## Integration Notes
|
|
|
|
When integrating with the game server:
|
|
1. Initialize the collection service at server startup
|
|
2. Load player collections on character login
|
|
3. Process item finds during gameplay
|
|
4. Handle collection completion through UI interactions
|
|
5. Save collections on logout or periodic intervals
|
|
6. Clean up resources during server shutdown |