Date: November 14, 2025
Version: 1.0-SNAPSHOT
NetworkDataAPI is designed with ONE primary purpose:
Provide a shared MongoDB connection pool for all plugins on a Minecraft server.
- ✅ A shared MongoDB connection pool manager
- ✅ A connection layer between plugins and MongoDB
- ✅ A high-level API for common database operations
- ✅ An automatic reconnection handler
- ✅ A caching layer to reduce database load
- ❌ An automatic player data manager
- ❌ A player tracking system
- ❌ A statistics/economy/cosmetics plugin
- ❌ A system that creates default data
NetworkDataAPI does NOT create any player data automatically. There are no default documents, no automatic player tracking, and no pre-defined data structures.
Why?
- Each plugin should control its own data
- Prevents unwanted data in the database
- Avoids conflicts between plugins
- Gives developers complete flexibility
Data should only be created when it's actually needed:
// ❌ WRONG: Create empty data on player join
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Document data = new Document("uuid", uuid).append("coins", 0);
collection.insertOne(data); // Why create empty data?
}
// ✅ CORRECT: Create data when relevant
public void claimCosmetic(Player player, String cosmeticId) {
Document data = collection.find(Filters.eq("uuid", uuid)).first();
if (data == null) {
// First cosmetic - NOW create the document
data = new Document("uuid", uuid).append("cosmetics", List.of(cosmeticId));
collection.insertOne(data);
}
}All plugins on a server share ONE connection pool:
Without NetworkDataAPI:
- Cosmetics Plugin: 10 connections
- Economy Plugin: 10 connections
- Stats Plugin: 10 connections
- Total: 30 connections per server!
With NetworkDataAPI:
- NetworkDataAPI: 1 shared pool (max 100 connections)
- All plugins use this shared pool
- Total: Max 100 connections, shared efficiently!
Each plugin gets its own MongoDB database:
NetworkDataAPIProvider api = APIRegistry.getAPI();
// Cosmetics plugin
MongoDatabase cosmeticsDB = api.getDatabase("cosmetics");
MongoCollection<Document> items = cosmeticsDB.getCollection("player_cosmetics");
// Economy plugin
MongoDatabase economyDB = api.getDatabase("economy");
MongoCollection<Document> balances = economyDB.getCollection("balances");Benefits:
- Complete data isolation
- No conflicts possible
- Easier backups per plugin
- Clear separation of concerns
All plugins use the default database but with separate collections:
NetworkDataAPIProvider api = APIRegistry.getAPI();
MongoDatabase db = api.getDatabase(); // Default from config
MongoCollection<Document> cosmetics = db.getCollection("cosmetics");
MongoCollection<Document> economy = db.getCollection("economy");Use when:
- Smaller plugins
- Need cross-plugin queries
- Simpler setup
The following features were removed to keep NetworkDataAPI focused on being a connection layer:
- Automatic PlayerConnectionListener registration - Removed
- Default player data creation - Removed
- Automatic join/quit tracking - Removed
- Game-specific default fields (coins, level, experience) - Removed
- PlayerDataService - Optional service for shared player data
- Direct MongoDB access - Full MongoDB API available
- Connection pooling - Shared pool for all plugins
- Caching - Optional caching layer
- REST API - Optional HTTP endpoints
- README.md - Quick overview and installation
- Installation guide - Step-by-step setup
- API_DOCUMENTATION.md - Complete API reference
- EXAMPLE_PLUGIN_GUIDE.md - Working example walkthrough
- Example Plugin - Full working code in
networkdataapi-example-plugin/
- CONTRIBUTING.md - Contribution guidelines
- Code structure - Well-documented source code
-
Always use async operations
CompletableFuture.supplyAsync(() -> { return collection.find(filter).first(); }).thenAccept(data -> { // Process result });
-
Create indexes for frequently queried fields
collection.createIndex(Indexes.ascending("uuid")); collection.createIndex(Indexes.descending("coins"));
-
Use dedicated databases for large plugins
MongoDatabase myDB = api.getDatabase("my_plugin");
-
Handle errors gracefully
.exceptionally(throwable -> { logger.error("Database error", throwable); return null; });
-
Create data only when needed (action-based)
- Not on player join
- Only when player performs relevant action
public class CosmeticsPlugin extends JavaPlugin {
private MongoDatabase database;
private MongoCollection<Document> playerCosmetics;
@Override
public void onEnable() {
NetworkDataAPIProvider api = APIRegistry.getAPI();
// Get dedicated database
database = api.getDatabase("cosmetics");
playerCosmetics = database.getCollection("player_cosmetics");
// Create indexes
playerCosmetics.createIndex(Indexes.ascending("uuid"));
}
// Data created when player claims cosmetic
public void claimCosmetic(Player player, String cosmeticId) {
UUID uuid = player.getUniqueId();
Document data = playerCosmetics.find(
Filters.eq("uuid", uuid.toString())
).first();
if (data == null) {
// First cosmetic - create document NOW
data = new Document()
.append("uuid", uuid.toString())
.append("claimed", List.of(cosmeticId))
.append("equipped", cosmeticId)
.append("firstClaim", System.currentTimeMillis());
playerCosmetics.insertOne(data);
} else {
// Add to existing
playerCosmetics.updateOne(
Filters.eq("uuid", uuid.toString()),
Updates.addToSet("claimed", cosmeticId)
);
}
}
}Default configuration provides:
- Min pool size: 10 connections
- Max pool size: 100 connections
- Shared across ALL plugins
This means:
- With 5 plugins, each effectively has access to 100 connections
- Much better than 5 × 10 = 50 separate connections
- Automatic load balancing across plugins
NetworkDataAPI includes built-in caching:
- Default: 10,000 entries max
- Expiry: 5 minutes after write, 10 minutes after access
- Reduces database load by 80%+
NetworkDataAPI is a pure connection layer that:
- Provides shared MongoDB connection pool
- Offers high-level API for convenience
- Handles automatic reconnection
- Provides optional caching
- Lets plugins control their own data
It does NOT:
- Track players automatically
- Create default data
- Make decisions about data structure
- Impose any data schema
Result: Maximum flexibility + Minimum resource usage
For more information, see the complete API documentation in API_DOCUMENTATION.md