Database API
DatabaseManager (com.xreatlabs.xdiscordultimate.database.DatabaseManager) is your gateway to link state, support tickets, moderation logs, and player stats. It is backed by a HikariCP connection pool and an async-first execution model — never talk to it synchronously on the main thread.
Async-First Model
Every mutating or lookup operation runs throughexecuteAsync, which off-threads the work onto the common pool and hands you back a CompletableFuture. The unit of work is the DatabaseOperation<T> functional interface:
Database calls in
DatabaseManager run on the ForkJoinPool common pool. Always hop back to the Bukkit scheduler (Bukkit.getScheduler().runTask(...)) before touching the Bukkit API from a future’s callback.Link State
Link an account
Unlink an account
Look up Discord from Minecraft (async)
Look up Minecraft from Discord
Async:Full account snapshot
getLinkedAccountInfoSync returns an immutable LinkedAccountInfo (or null):
LinkedAccountInfo getters: getDiscordId(), getDiscordName(), getMinecraftName(), getMinecraftUuid(), getLinkedAt().
Tickets, Moderation, and Stats
These helpers cover the rest of the schema:| Method | Returns | Notes |
|---|---|---|
createTicket(UUID player, String subject) | CompletableFuture<Integer> | New ticket ID |
updateTicketChannel(int ticketId, String channelId) | CompletableFuture<Boolean> | Attach Discord channel |
closeTicket(int ticketId) | CompletableFuture<Boolean> | Mark CLOSED |
addTicketMessage(int ticketId, UUID sender, String senderType, String message) | CompletableFuture<Boolean> | Append a message |
getOpenTicketsCount(UUID player) | CompletableFuture<Integer> | Open ticket count |
logModerationAction(String type, UUID target, UUID moderator, String reason, Timestamp expires) | CompletableFuture<Void> | Audit row |
createReport(UUID reporter, UUID target, String reason) | CompletableFuture<Integer> | New report ID |
hasRecentReport(UUID reporter, int cooldownMinutes) | CompletableFuture<Boolean> | Cooldown check |
updatePlayerStats(UUID player, String statType, int increment) | CompletableFuture<Void> | Increment a stat column |
updateDiscordName(String discordId, String newName) | CompletableFuture<Boolean> | Refresh stored display name |
Raw SQL Escape Hatch
For anything the typed methods don’t cover, borrow a connection straight from the pool. Always close it in a try-with-resources and always parameterize user input.Never build SQL with string concatenation. Discord IDs and usernames come from untrusted sources — concatenate and you ship a SQL injection. Use
? placeholders and the setXxx setters, every time.Verification Codes
The verification flow stores short-lived codes (sync API — safe because they are only touched from Discord events, which run off the main thread):VerificationCode getters: getDiscordId(), getCode(), getUsername(), getCreatedAt(), getExpiresAt(), plus isExpired().
Schema
XDiscordUltimate creates and migrates these tables on startup:| Table | Key columns |
|---|---|
verified_users | minecraft_uuid (PK), discord_id (UNIQUE), verified_at, minecraft_name, discord_name |
verification_codes | discord_id (PK), code (UNIQUE), username, created_at, expires_at |
tickets | id, minecraft_uuid, discord_channel_id, status, created_at, closed_at, subject |
ticket_messages | id, ticket_id, sender_uuid, sender_type, sent_at |
moderation_logs | id, action_type, moderator_uuid, reason, timestamp, expires_at, active |
player_stats | minecraft_uuid (PK), joins, messages_sent, deaths, playtime_minutes, last_seen, first_join |
activity_rewards | id, discord_id, reward_type, reward_data, claimed, created_at, claimed_at |
schema_versions | version_key (PK), version_value, applied_at |
Connection Pool
All connections come from a HikariCP pool with these settings:| Setting | Value |
|---|---|
maximumPoolSize | 10 |
minimumIdle | 2 |
idleTimeout | 600000 ms |
connectionTimeout | 30000 ms |
leakDetectionThreshold | 60000 ms |
Next Steps
Event Bus
React to
PlayerVerifiedEvent instead of polling the database.API Overview
Back to the API introduction and core services.

