Compatibility
SilkMC is designed to be more forgiving than upstream Folia without hiding correctness problems. This page describes the compatibility policy, configurable behavior, and the boundaries SilkMC will not cross for the sake of compatibility.
Current policy
silk-supported: trueis the preferred plugin metadata flag.folia-supported: trueis still accepted for upstream interoperability.- Every plugin JAR is inspected by
SilkPluginCompatibilityManagerbefore enable: metadata read, classes byte-scanned for API and NMS usage, then assigned one ofSAFE/COMPATIBLE/UNSAFE/UNKNOWN. - Legacy Bukkit scheduler calls (
runTask,runTaskLater,runTaskTimer,callSyncMethod) are bridged to the Global Region Scheduler. - Legacy synchronous
Entity.teleport()andPlayer.teleport()are bridged toteleportAsyncwhen the call is made on the owning region; cross-region sync teleports warn and return optimistically. - The plugin lifecycle (enable/disable) is wrapped in a compatibility context so failures can be classified and reported with operator-friendly messages.
Classification
| Class | Trigger | Action |
|---|---|---|
SAFE | Declares silk-supported or folia-supported. | Load normally. |
COMPATIBLE | Uses Bukkit/Spigot/Paper APIs but no unsafe patterns. | Load under the shim layer (scheduler bridge, teleport bridge). |
UNSAFE | Async scheduling combined with direct NMS-level world access. | Refuse to load; print a structured rejection log; continue startup. |
UNKNOWN | No detectable APIs or unreadable JAR. | Refuse under strict mode; allowed with warning if allow-unknown-plugins: true. |
Modes
- Compatibility warning mode for unmarked plugins (default).
- Strict supported-plugin enforcement.
- Automatic disabling for plugins that hit known unsafe compatibility boundaries.
- Upstream enum compatibility toggles through
bukkit.yml.
Fail-safe behavior
When SilkMC cannot safely emulate a legacy expectation, it should:
- Stop the unsafe operation.
- Disable the plugin when the failure matches a known compatibility boundary.
- Log a clear operator-facing reason.
- Preserve server stability.
SilkMC currently classifies and disables plugins for known startup or task-time failures such as:
- World and chunk access from the wrong thread or region context.
- Global-region-only operations triggered from an ambiguous legacy context.
- Legacy scheduler paths that still lack enough ownership context to bridge safely.
- Synchronous teleport assumptions that cannot be preserved safely.
Each classified failure produces a log entry with the plugin display name, the lifecycle phase
(startup, async scheduler task, global region task, …), a one-paragraph
operator-facing reason, and optionally the original stack trace.
Stability rules
never
SilkMC will not, under any compatibility policy:
- Fake region ownership to silence a thread check.
- Pretend a cross-region operation succeeded when it actually didn't write.
- Introduce a fake global "main" thread that mutates world state.
- Corrupt world or player data to keep a plugin running.
Known limitations
- No fake global main thread is introduced.
- Plugins that mutate cross-region state unsafely can still fail.
- Some traditional Bukkit scheduler tasks still lack enough location or entity context for SilkMC to infer the safest owning region and are routed to the global region scheduler.
- Some event ordering assumptions from traditional single-threaded servers remain impossible to preserve fully.
- Some plugins detect "Folia" by class name lookup; the upstream classes still exist under their original packages for binary compatibility, but plugins that hard-fail on Folia detection should be updated to recognize SilkMC's brand.