
XGamemode
You're not switching modes, you're switching dimensions.
2.0K
4
API Security
beta29 апреля 2026 г.Added
- API security control:
allow_to_use_apiconfig option (default: true) to prevent other plugins from accessing the API when set to false IllegalStateExceptionwith clear message when API access is disabled
Fixed
- None
Changed
- None
Removed
- None
More Stable
alpha24 апреля 2026 г.Added
- Storage type change detection on reload - warns admin to restart server instead of loading mismatched data
Fixed
MAX_MAPPINGSlimit now trims oldest entries instead of only warning- YAML name fallback uses full UUID string instead of
substring(0, 8)to prevent potential boundary issues
Changed
lastStorageTypefield tracks storage type across reloads for change detection
Final fixes
release23 апреля 2026 г.Added
- Folia scheduler support with automatic fallback to Bukkit scheduler
- SQLite ON CONFLICT detection for better UPSERT performance
- UUID-based write locks for thread-safe player data operations
- Player save queue (
pendingSaves) to serialize async database writes per UUID - Offline player name caching to reduce I/O operations during batch processing
- YAML save debouncing with resettable timer (
scheduleYamlSave) - Atomic reference for
nameToUUIDsanduuidToNamemaps for safe reload - Legacy YAML format detection and migration support (
uuid: GAMEMODE) - Support for setting gamemode for players who have never joined the server
GamemodeChangeEventcustom event for API integration-all,-online,-offlinebatch operation flags- Database transaction support for batch offline player updates
- Automatic config.yml key merging with missing defaults preservation
- Connection retry mechanism with configurable attempts and delay
- Debug logging controlled by config option
Fixed
- NPE in
onDisable()whenstorageTypeis not"yaml"andyamlCacheis null - Race condition in
onPlayerJoinwhere async save could overwrite recently set gamemode - SQL operation silent failure - now logs error after max retry attempts
- Write lock timeout now logs debug message instead of failing silently
- Skipped offline players during batch operations now logged with warning count
- Config merge now properly adds missing keys without overwriting existing values
- Migration now handles both legacy (flat) and modern (nested) YAML formats
Changed
- Replaced
pendingSavesSet<String>withMap<UUID, CompletableFuture<Void>>for per-UUID queuing - Refactored
tryWriteLockpattern intowithWriteLockhelper method - Optimized
processOfflinePlayersDatawith name cache and early empty check - Cached UPSERT SQL generation to avoid repeated ON CONFLICT detection
- Message placeholder replacement now uses
Matcher.quoteReplacement()to escape$and\ - Folia reflection now uses
Consumer.classwith proper generic erasure handling savePlayerModeDirectnow updates memory cache immediately before async DB write- Batch migration now uses incremental
executeBatch()to avoid memory issues
Removed
- Legacy
yamlCache.set(uuid.toString(), mode.name())flat format write - Redundant
saveYamlCache()call when using database storage - Unused
SAVE_DELAYfield from earlier versions
Optimizations lol
beta20 апреля 2026 г.Added
- Added database connection retry mechanism with
MAX_RETRY_ATTEMPTS(3) andRETRY_DELAY_MS(1000ms) for MySQL/SQLite. - Added
ensureConnection()andreconnect()methods for automatic database connection recovery. - Added
executeWithRetry(),executeUuidQueryWithRetry(), andexecuteVoidWithRetry()helper methods to wrap SQL operations with retry logic. - Added cross-server compatibility for offline player targeting: When a player name is not found in the local memory cache (
nameToUUIDs), the plugin now queries the database directly viaqueryUuidByName(). - Added
-offline,-online, and-allflags to batch target processing. - Added
PlayerQuitEventhandler to clean upplayerLockswhen a player disconnects, preventing potential memory leaks. - Added proper index creation handling (
createIndexSafe) with fallback checks for MySQL vs SQLite metadata differences. - Added
GamemodeChangeEventcustom event that is called when a player's gamemode is changed by the plugin.
Fixed
- Fixed database index creation to check for existing indexes before attempting
CREATE INDEXto prevent SQL errors on MySQL. - Fixed
onPlayerJoinevent to useOptionalforloadPlayerModeand properly handle null stored gamemodes without triggering unnecessary errors. - Fixed
savePlayerModeto ensure player name is correctly updated in the database when saving gamemode. - Fixed
setPlayerModeAPI method to handle exceptions and returnfalseon failure rather than always returningtrue. - Fixed YAML caching to properly wrap saves in
synchronizedblocks to prevent concurrent modification issues. - Fixed
loadDatato properly populatenameToUUIDsanduuidToNamemappings from both YAML and SQL storage. - Fixed
handleSinglePlayerto check for player name in database when local cache misses, improving cross-server or bungeecord network support. - Fixed
processOfflinePlayersDatato use database batch operations for SQL storage instead of locking each player individually, greatly improving performance.
Changed
- Refactored database initialization to use a dedicated
dbUrl,dbUser, anddbPassfields instead of constructing the connection string inline. - Updated
loadPlayerModeto useexecuteWithRetryfor robust SQL error handling andOptional<GameMode>return type. - Improved
setPlayerGamemodeLockedlogic to checkplayer.isOnline()before scheduling tasks. - Enhanced
handleGamemodeTargetto useasync()for both batch and single player operations to avoid blocking the main thread. - Replaced explicit
try-catchblocks withexecuteWithRetrywrappers in database operations for cleaner code. - Changed
handleBatchPlayersandhandleSinglePlayerto usesync()for sending messages to ensure thread safety. - Improved
migrateFromYamlIfNeededto handleON DUPLICATE KEY UPDATEproperly on MySQL. - Optimized
processOfflinePlayersDatato use batch SQL execution (executeBatch()) withBATCH_SIZEinstead of individual updates.
Removed
- Removed
tryReadLock(),unlockRead(), andwithReadLock()methods as they were unused in the new version. - Removed
saveAllSync()method as it was unused. - Removed direct
Statementusage ininitDatabase()in favor of try-with-resources and prepared statements. - Removed redundant player mode saving in
onPlayerJoin(no longer forces save if gamemode didn't change). - Removed manual thread sleeping in
processOfflinePlayersDatafor SQL storage, as batch processing handles this efficiently.
Major Change...
alpha18 апреля 2026 г.Added
- Multi-storage support with automatic migration (YAML, SQLite, MySQL)
- Database connection pooling preparation structure
- Automatic YAML to database migration on first load
- Fallback mechanism to YAML when database connection fails
- ReadWriteLock implementation for finer-grained concurrency control
- Separate read/write lock methods (
tryReadLock,tryWriteLock,unlockRead,unlockWrite) withReadLockandwithWriteLockhelper methods for cleaner lock management- Comprehensive API methods with
CompletableFuturereturn types (getPlayerMode,setPlayerMode) - Custom
GamemodeChangeEventfor third-party plugin integration - Static
Main.getInstance()API accessor - Dedicated
savePlayerModeandloadPlayerModemethods with storage abstraction saveAllSyncmethod for batch YAML persistencecloseStoragemethod for proper database connection cleanup- Storage type logging on startup when debug mode is enabled
- Player lock map initialization with
ReentrantReadWriteLock - Database index creation for player name lookups with fallback for SQLite compatibility
Fixed
- Lock ownership checking before unlocking to prevent
IllegalMonitorStateException - Thread interruption handling in lock timeout scenarios with proper flag restoration
- Concurrent modification safety in batch player processing
- Data consistency between online player state and persistent storage
- Proper thread interruption propagation during executor shutdown
- Offline player name resolution fallback chain
- UUID validation with proper exception handling for malformed entries
- Batch processing now includes invalid entry removal and reporting
- YAML cache synchronization issues with
synchronizedblocks - Pending save deduplication using
ConcurrentHashMap.newKeySet()
Changed
- Storage backend from single YAML file to pluggable architecture (YAML/SQLite/MySQL)
- Lock mechanism from
ReentrantLocktoReentrantReadWriteLockfor improved read concurrency - Database operations execute asynchronously with prepared statements
- Player mode saving now includes timestamp field for future audit capabilities
- Data file renamed from
data.ymlto structured format with separatenameandgamemodefields - Configuration now supports
storagesection with type, MySQL credentials, and connection parameters - Migration process creates
.bakbackup of original YAML file handleGamemodeTargetsplit intohandleBatchPlayersandhandleSinglePlayerfor clarityprocessOfflinePlayersDatanow returnsPlayerDataResultwith changed and removed counts- Lock acquisition timeout reduced from lock-per-operation to centralized timeout constant
saveDataAsyncandsaveDataSyncreplaced with storage-awaresavePlayerModeandsavePlayerModeLocked- Executor service now uses fixed thread pool of 4 instead of cached pool
detectServerVersionmethod removed as no longer needed for SPECTATOR detection- Database connection uses MySQL connection parameters (useSSL=false, serverTimezone=UTC, autoReconnect=true)
- YAML cache field renamed from
dataConfigtoyamlCachefor clarity
Removed
PlayerDataResultinner class (functionality merged into improved batch processing)serverMinorVersionfield and version-specific SPECTATOR availability checkingsaveDataSyncdirect public method (replaced bysaveYamlCache)updateMappingstandalone method (merged into player join event handling)processPlayerSethelper method (consolidated into main processing flow)- Direct
dataConfigfield exposure (now accessed through synchronizedyamlCache) - Inline database connection string building (moved to dedicated
initDatabasemethod) - Redundant gamemode name storage in YAML root level (now only stored in structured format)
