Skip to content

Kyokalith v1.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 17 Jul 14:16

Folia support was contributed by RiceChen_ (RICE0707) in #1 — including the source-set isolation that keeps folia-api off the main compile classpath. Thank you!

Added

  • Folia support. folia-supported: true is declared, and every scheduled task now runs on the thread that owns the data it touches: block work on the owning region, /kyo giveeligible on the recipient's entity scheduler, and the dirty-position flush (which only writes SQLite) on the global region. Spigot and Paper behaviour is unchanged — the same code path resolves to Bukkit.getScheduler() there. The startup line reports which mode is active (scheduler: Folia regionized / Bukkit main thread).
  • Admin commands that read or write blocks (inspect, preview, sample, markeligible, resolve) now run on the thread that owns the target coordinate — inline when the current thread already owns it, scheduled onto the owning region otherwise. On Folia a console command runs on the global thread, which owns no blocks at all, so these would otherwise have thrown. Spigot and Paper always dispatch commands on the main thread, so the inline path is always taken there and replies — including over RCON — behave exactly as in 1.1.0. Known limit: on Folia, an RCON command that has to hop regions gets an empty RCON response (the response buffer is flushed when dispatch returns and cannot wait for another thread).

Changed

  • Folia's scheduler API is compiled in a separate folia source set, not added to main. folia-api transitively exposes the whole Paper API, so putting it on main's compile classpath would have silently retired the [1.0.0] guarantee that Spigot compatibility is a compile-time fact. main still sees only spigot-api; the one file that calls Folia (FoliaSchedulers) is loaded only when running on Folia, and SchedulersSpigotSafetyTest fails if a Folia reference ever reaches the class Spigot does load.
  • database.dirty_flush_interval_ticks below 1 is now clamped to 1. Bukkit silently did this already; Folia rejects it outright, so the same config would have failed startup there.
  • api-version lowered from 26.2 to 26.1. Folia's newest release is 26.1.2 — no 26.2 build exists — and a server refuses to load a plugin whose api-version is above its own version, so this is the price of one jar running on all three platforms. The compile baseline is unchanged (spigot-api 26.2); on Spigot/Paper 26.2 the plugin now merely declares the older API level.

Fixed

  • Dirty positions could be lost on Folia, which is an exploit problem rather than mere data loss — a dropped dirty flag makes a block a player covered up "first-exposure resolvable" again, reopening the cover-and-dig hole. Each chunk's position set was a plain HashSet, safe on Spigot only because markDirty and the flush task shared the main thread. Under regionized scheduling the flush runs on the global thread and encodes the set while a region thread is still adding to it, throwing ConcurrentModificationException mid-write. The per-chunk sets are now concurrent; DirtyPositionConcurrencyTest reproduces the original failure. Spigot and Paper were never affected.
  • A failed dirty-position flush no longer drops the chunk from the flush queue: the chunk is requeued for the next cycle and the failure is logged, and one chunk's failure no longer aborts the rest of the cycle. Relevant on Folia, where region threads and the global flush task can hit SQLite concurrently and collide with SQLITE_BUSY; previously the pending flag was consumed before the write, so a failed write meant those dirty positions were never retried — the same exploit-reopening loss the flush-interval note in CONFIG.md warns about.