Plugins · 01

Plugin developers

This guide is for plugin authors targeting SilkMC. It covers the metadata SilkMC understands, the compatibility behaviors it provides, and the patterns that travel best across Paper, Folia, and SilkMC.

Recommended metadata

Add this to plugin.yml:

silk-supported: true

SilkMC also honors the legacy upstream key:

folia-supported: true

Either flag is sufficient. Marking your plugin tells SilkMC you have at least reviewed the regional threading model and consider your plugin compatibility-aware.

Practical guidance

What SilkMC tries to help with

What SilkMC will not do

Patterns that travel well

// Schedule on the entity's owning region
entity.getScheduler().run(plugin, task -> {
    entity.setHealth(20);
}, null);

// Schedule global tick work
Bukkit.getGlobalRegionScheduler().run(plugin, task -> { /* ... */ });

// Async teleport (works on Paper, Folia, SilkMC)
player.teleportAsync(target).thenAccept(success -> { /* ... */ });

Patterns to avoid on SilkMC

// Legacy sync schedule with no region context.
// SilkMC bridges this through the Global Region Scheduler, but plugins should
// migrate to the region/entity/global schedulers explicitly.
Bukkit.getScheduler().runTaskTimer(plugin, () -> { /* ... */ }, 0L, 20L);

// Synchronous cross-world teleport in a tick callback.
// SilkMC will warn and return optimistically; the actual teleport runs async.
entity.teleport(somewhereInAnotherWorld);

Detection

Plugins that want to identify the server platform can check Bukkit.getServer().getName() or ServerBuildInfo. SilkMC reports brand SilkMC with key gg.tame:silkmc. The upstream Folia classes still exist under their original packages for binary compatibility, so feature-detection (rather than name-detection) remains the most reliable approach.