Changelog
All notable changes to IPDynamic will be documented in this file.
[2.0.0] - 2026-03-24
Complete Rewrite - Premium Edition
This release is a complete ground-up rewrite of IPDynamic. Every file has been redesigned for production-grade quality, performance, and extensibility. The plugin has been upgraded from 13 source files to 78 source files across a clean modular architecture.
Backward Compatible: Existing v1.x databases are automatically upgraded on first startup. No data loss, no manual migration required.
Architecture
Database Layer
- HikariCP Connection Pool - Replaced single raw JDBC connection with HikariCP (pool size 3). Eliminates race conditions and
database is locked errors under load.
- Repository Pattern - Split the monolithic 462-line
DatabaseManager into 7 focused repositories (PlayerRepository, ConnectionRepository, IPRecordRepository, BanRepository, WhitelistRepository, AuditRepository, CountryRuleRepository), each under 150 lines.
- Transactional Writes - Multi-statement operations (player registration, IP record upsert) now use proper database transactions with commit/rollback.
- Idempotent Player Registration - Replaced SELECT-then-INSERT pattern with
INSERT OR IGNORE + UPDATE to prevent race conditions when two connections for the same new player arrive simultaneously.
- Per-Connection PRAGMAs - SQLite
journal_mode=WAL, foreign_keys=ON, and busy_timeout=5000 are now applied to every pool connection via connectionInitSql, not just the first one.
- Auto-Adaptive Schema -
SchemaManager creates missing tables, adds missing columns, and creates missing indexes without ever dropping data. Seamless upgrade from any v1.x database.
Service Layer
- 9 dedicated services with single responsibility:
GeoIPService, BanService, WhitelistService, AltDetectionService, VPNDetectionService, CountryService, AuditService, AlertService, DataRetentionService.
- lateinit initialization - All services use
lateinit var with proper error handling. If initialization fails, the plugin disables itself cleanly instead of running in a broken state with null references.
- Coroutine Scoping - All async operations use
MCCoroutine.launch with proper dispatchers. Database I/O runs on Dispatchers.IO, never blocking the main server thread.
Command System
- SubCommand Pattern - Replaced the 560-line monolithic command class with
CommandRegistry + 15 individual command implementations, each focused and under 100 lines.
- Adventure API - All command output uses clickable and hoverable text components. Player names link to
/ipdy check, IP addresses link to /ipdy ip, UUIDs are copy-to-clipboard.
- Pagination - List commands (
history, banlist, whitelist list, audit) feature clickable [<< Prev] / [Next >>] page navigation.
Caching
- ExpiringCache - Generic TTL cache with LRU eviction. Configurable max size and time-to-live. Replaces the old unbounded
ConcurrentHashMap that could cause memory leaks.
- BanPatternIndex - Trie-based data structure for O(1) IP ban pattern matching. Replaces the old O(n) linear scan that iterated all bans for every player login.
New Features
VPN/Proxy Detection
- Detect VPN, proxy, and hosting provider connections on player join.
- Configurable action:
ALERT (notify staff), KICK (disconnect player), or BAN (auto-ban range).
- Uses extended GeoIP API fields (
proxy, hosting, isp) from ip-api.com.
- Dedicated VPN results cache with separate TTL (default 120 minutes).
- Whitelisted players can bypass VPN checks (configurable).
Country Restriction System
- Block or allow players by country with
BLACKLIST or WHITELIST mode.
- Use full country names in config:
"Chile", "Russia", "United States" (no cryptic ISO codes).
- Runtime management via
/ipdy country add <name> and /ipdy country remove <name>.
- Persistent storage - Country rules added via commands are saved to the database and survive reloads/restarts.
- Config.yml countries serve as base rules; database rules are merged on startup.
Staff Alert System
- Real-time notifications to online staff with the
ipdynamic.alerts permission.
- Alert types: alt detected, VPN detected, new IP, country change.
- Optional alert sound (configurable
pling notification).
- Each alert type individually toggleable in config.
First-Join Console Notification
- Professional formatted console notification when a brand-new player joins for the first time.
- Shows: username, IP address, country, and detected alt accounts.
- Disabled by default (
first-join-console: false in config).
- Fully customizable message template in
messages.yml.
Audit Log
- Immutable audit trail for all administrative actions.
- Tracks: who performed the action, what action, target, details, timestamp.
- Actions logged: ban add/remove, whitelist add/remove, country add/remove, reload, export, import, VPN kick, country kick.
- Viewable via
/ipdy audit [page] with pagination.
- Configurable retention: auto-cleanup entries older than
audit-max-days (default 90 days).
Data Retention
- Automatic cleanup of old connection records to prevent unbounded database growth.
- Configurable:
connections-max-days (default 180 days) and audit-max-days (default 90 days).
- Runs on a configurable interval (default every 24 hours).
- Disabled by default - enable in
config.yml when needed.
Rate Monitoring
- Detects potential bot attacks by monitoring connection rates per /24 IP range.
- Sliding window algorithm with configurable threshold and window size.
- Fires
SuspiciousActivityEvent when threshold exceeded for webhook/alert integration.
CIDR Ban Support
- New ban type alongside OP1/OP2: CIDR notation (e.g.,
/ipdy ban cidr/24 192.168.1.0 reason).
- Bitwise prefix matching for accurate CIDR range calculations.
- Estimated IP count display for all ban types.
Export/Import
- Export bans or whitelist to JSON files:
/ipdy export bans, /ipdy export whitelist.
- Import from JSON files:
/ipdy import bans, /ipdy import whitelist.
- Files saved in the plugin data folder.
Public API
IPDynamicAPI interface for other plugins to integrate with.
- Access via Bukkit's
ServicesManager.
CompletableFuture returns for async operations (profiles, alts, GeoIP).
- Direct synchronous returns for cached data (ban checks, whitelist checks).
PlaceholderAPI Integration
- 9 placeholders under the
%ipdynamic_*% namespace:
%ipdynamic_country% - Player's country
%ipdynamic_country_code% - Country ISO code
%ipdynamic_connections% - Total connection count
%ipdynamic_alts% - Number of alt accounts
%ipdynamic_is_banned% - Whether player's IP is banned
%ipdynamic_is_whitelisted% - Whether player is whitelisted
%ipdynamic_is_vpn% - Whether player is on VPN/proxy
%ipdynamic_ban_count% - Total active bans
%ipdynamic_whitelist_count% - Total whitelisted players
Event System
- 6 custom async Bukkit events for other plugins to listen to:
AltDetectedEvent - Alt account detected on join
VPNDetectedEvent - VPN/proxy detected on join
NewIPDetectedEvent - Player connected from new IP
FirstJoinEvent - Brand-new player's first connection
CountryBlockedEvent - Player blocked by country restriction
SuspiciousActivityEvent - Rate anomaly detected
New Configuration
config.yml (NEW)
Full plugin configuration file with sections for:
- Database (pool size, filename)
- GeoIP (providers, cache TTL, max size, request timeout)
- VPN detection (enabled, action, providers, cache TTL, whitelist bypass)
- Country restriction (enabled, mode, country names, kick message)
- Staff alerts (enabled, per-type toggles, permission, sound)
- Data retention (enabled, max days for connections and audit, cleanup interval)
- Pagination (page size)
- Rate monitoring (enabled, threshold, window)
messages.yml (EXPANDED)
- All existing v1 messages preserved.
- New sections: VPN messages, country restriction messages, audit messages, alert formats, pagination format, first-join console notification, export/import messages.
New Commands
| Command |
Permission |
Description |
/ipdy country add <name> |
ipdynamic.country |
Add country to restriction list |
/ipdy country remove <name> |
ipdynamic.country |
Remove country from restriction list |
/ipdy country list |
ipdynamic.country |
View restricted countries |
/ipdy audit [page] |
ipdynamic.audit |
View audit log with pagination |
/ipdy export <bans|whitelist> |
ipdynamic.export |
Export data to JSON file |
/ipdy import <bans|whitelist> |
ipdynamic.import |
Import data from JSON file |
New Permissions
| Permission |
Default |
Description |
ipdynamic.country |
OP |
Manage country restrictions |
ipdynamic.audit |
OP |
View audit log |
ipdynamic.export |
OP |
Export plugin data |
ipdynamic.import |
OP |
Import plugin data |
ipdynamic.alerts |
OP |
Receive staff alerts |
Performance Improvements
| Area |
Before (v1) |
After (v2) |
Improvement |
| Ban checking |
O(n) linear scan all bans |
O(1) trie lookup |
Constant time regardless of ban count |
| GeoIP cache |
Unbounded, no TTL, no eviction |
TTL + LRU eviction + max size |
No more memory leaks |
| GeoIP rate limiting |
None (429 errors under load) |
Token bucket 40 req/min |
No more API bans |
| DB connections |
Single shared JDBC connection |
HikariCP pool (3 connections) |
No more race conditions |
| Username lookups |
LOWER() function (full table scan) |
COLLATE NOCASE (uses index) |
Index-accelerated queries |
| Player registration |
SELECT-then-INSERT (race condition) |
INSERT OR IGNORE + UPDATE |
Idempotent, no PK violations |
| SQLite PRAGMAs |
Applied to 1st connection only |
Applied to ALL pool connections |
Consistent behavior |
Database Changes
New Tables
audit_log - Administrative action audit trail
country_rules - Persistent country restriction rules
New Columns
| Table |
Column |
Type |
Purpose |
connections |
is_vpn |
INTEGER |
VPN detection flag |
connections |
is_proxy |
INTEGER |
Proxy detection flag |
connections |
isp |
TEXT |
ISP name from GeoIP |
ip_bans |
cidr_notation |
TEXT |
CIDR ban range notation |
ip_bans |
source_ip |
TEXT |
Original IP that triggered the ban |
New Indexes
idx_connections_username on connections(username COLLATE NOCASE) - Fixes full table scan on history queries
All schema changes are additive. Existing data is never modified or deleted during upgrade.
Dependencies
| Dependency |
Version |
Purpose |
| HikariCP |
5.1.0 |
NEW - Connection pool |
| PlaceholderAPI |
2.11.6 |
NEW - Optional soft dependency |
| Paper API |
1.20.4 |
Server integration |
| MCCoroutine |
2.20.0 |
Async operations |
| Kotlin Coroutines |
1.8.1 |
Concurrent programming |
| SQLite JDBC |
3.44.1.0 |
Database driver |
| Gson |
2.10.1 |
JSON parsing |
Migration Guide
From v1.x to v2.0
- Stop your server.
- Backup your
plugins/IPDynamic/ folder (especially ipdynamic.db).
- Replace the old JAR with
IPDynamic.jar (v2.0).
- Delete the old
config.yml if it exists (v2.0 generates a new one with all options).
- Start the server.
- The plugin will:
- Generate a new
config.yml with all v2.0 options.
- Automatically upgrade your existing database (add new columns, create new tables).
- Preserve all existing player data, connections, bans, and whitelist entries.
- Review
config.yml and adjust settings to your preference.
Important Notes
messages.yml is also regenerated with new sections. If you customized it, back it up and re-apply your changes to the new file.
- Country restrictions now use full country names (e.g.,
"Chile") instead of ISO codes (e.g., "CL").
- The
first-join-console feature is disabled by default. Enable it in config.yml under alerts:.
Project Structure
com/ipdynamic/
├── IPDynamicPlugin.kt # Main plugin class
├── api/ # Public API (2 files)
├── cache/ # ExpiringCache + BanPatternIndex (2 files)
├── command/ # SubCommand + CommandRegistry
│ ├── impl/ # 15 command implementations
│ └── util/ # Pagination
├── config/ # PluginConfig + MessageConfig
│ └── model/ # 6 settings data classes
├── database/ # DatabaseManager + SchemaManager
│ └── repository/ # 7 repositories
├── event/ # 6 custom Bukkit events
├── integration/ # PlaceholderAPI expansion
├── listener/ # 3 event listeners
├── model/ # 12 data models
├── service/ # 9 business logic services
├── task/ # 3 scheduled tasks
└── util/ # 4 utility classes
Total: 78 Kotlin source files | 17 packages | 3 resource files
Compatibility
| Server Version |
Status |
| 1.17.x |
Supported |
| 1.18.x |
Supported |
| 1.19.x |
Supported |
| 1.20.x |
Supported |
| 1.21.x |
Supported |
| Server Software |
Status |
| Paper |
Fully Supported |
| Spigot |
Supported |
| Java Version |
Status |
| Java 17+ |
Required |