RankForge API Best Practices – Threads, Folia & Compatibility
1. Threading and Folia Compatibility
Section titled “1. Threading and Folia Compatibility”| Operation | Thread Safety |
|---|---|
get* (reading points, tiers, stats) |
Safe from any thread |
setPoints, addPoints, removePoints |
Server thread only (main thread on Paper, region thread on Folia) because it dispatches synchronous events |
saveAsync() |
Safe from any thread (returns CompletableFuture) |
- When calling mutation methods from async contexts, schedule onto the server thread using
Bukkit.getGlobalRegionScheduler().execute(...)(compatible with both modern Paper and Folia). getPlayerData()returns an active data instance that can be updated concurrently. Read needed values into local variables rather than storing long-lived object references.
2. Always Handle null
Section titled “2. Always Handle null”getTier, getTierByPoints, and getNextTier return null for unranked players or players at the top tier.
Tier tier = api.getTier(player);String name = tier != null ? tier.display : "Unranked";3. Resilient Soft-Dependency Pattern
Section titled “3. Resilient Soft-Dependency Pattern”- Use
softdepend: [RankForge]inplugin.yml. - Isolate RankForge-dependent code into dedicated bridge classes to prevent
NoClassDefFoundErrorwhen RankForge is absent. - Check
RankForgeAPI.isAvailable()before callingRankForgeAPI.get().
4. Rely Exclusively on Public API Packages
Section titled “4. Rely Exclusively on Public API Packages”Only classes inside xyz.noxlydev.rankforge.api.* and xyz.noxlydev.rankforge.model.* are public and guaranteed stable. Internal packages are obfuscated with ProGuard and may change without notice.
5. Avoid Event Recursion
Section titled “5. Avoid Event Recursion”Never invoke addPoints or setPoints within a PlayerPointsChangeEvent handler. Use event.setNewPoints(...) instead to alter values.
