feat: Folia support

This commit is contained in:
Keisuke Hirata 2026-03-11 17:15:56 +09:00
parent 7eb0534d21
commit 9673e1e6e9
2 changed files with 23 additions and 4 deletions

View File

@ -25,7 +25,7 @@ class AttachmentSynchronizer(
permissible: Permissible,
patch: AttachmentPatch,
) {
ThreadChecks.ensurePrimaryThread("AttachmentSynchronizer.applyPatch")
ThreadChecks.ensureRegionThread("AttachmentSynchronizer.applyPatch", permissible)
if (patch.changes.isEmpty()) return
val handle = ensureHandle(permissible)
patch.changes.forEach { (id, value) ->
@ -58,7 +58,7 @@ class AttachmentSynchronizer(
}
fun clear(permissible: Permissible) {
ThreadChecks.ensurePrimaryThread("AttachmentSynchronizer.clear")
ThreadChecks.ensureRegionThread("AttachmentSynchronizer.clear", permissible)
handles.remove(permissible)?.attachment?.remove()
}

View File

@ -1,11 +1,30 @@
package net.hareworks.permits_lib.util
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.permissions.Permissible
internal object ThreadChecks {
/**
* For Bukkit-global operations (e.g. PluginManager permission registration).
* In Folia there is no single primary thread; callers should ensure they run
* on the global region scheduler (e.g. during onEnable / onDisable).
*/
fun ensurePrimaryThread(action: String) {
check(Bukkit.isPrimaryThread()) {
"$action must be invoked from the primary server thread."
// no-op for global ops: Folia has no single primary thread.
// PluginManager operations are safe when called from onEnable/onDisable
// or from the global region scheduler.
}
/**
* For player-bound operations (e.g. PermissionAttachment mutation).
* Verifies that the current thread owns the region for the given [permissible].
* Non-player permissibles are skipped since they have no region owner.
*/
fun ensureRegionThread(action: String, permissible: Permissible) {
val player = permissible as? Player ?: return
check(Bukkit.isOwnedByCurrentRegion(player)) {
"Action '$action' must be called on the owning region thread for ${player.name}"
}
}
}