https://github.com/slne-development/surf-api
Multi-platform plugin API framework with modular service discovery, lifecycle-managed components, and NMS bridge abstractions for multiple server platforms.
https://github.com/slne-development/surf-api
api kotlin nms packet packets paper papermc utility velocity
Last synced: 7 days ago
JSON representation
Multi-platform plugin API framework with modular service discovery, lifecycle-managed components, and NMS bridge abstractions for multiple server platforms.
- Host: GitHub
- URL: https://github.com/slne-development/surf-api
- Owner: SLNE-Development
- License: gpl-3.0
- Created: 2025-02-10T21:46:43.000Z (over 1 year ago)
- Default Branch: version/26.1
- Last Pushed: 2026-05-25T12:43:17.000Z (19 days ago)
- Last Synced: 2026-05-25T14:28:48.901Z (19 days ago)
- Topics: api, kotlin, nms, packet, packets, paper, papermc, utility, velocity
- Language: Kotlin
- Homepage: https://docs.slne.dev/surf-api
- Size: 14.9 MB
- Stars: 5
- Watchers: 0
- Forks: 0
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# surf-api
**Multi-platform plugin API framework** for Minecraft servers — providing modular service
discovery, lifecycle-managed components, NMS bridge abstractions, and rich DSLs across Paper,
Velocity, and Standalone platforms.
[](https://github.com/SLNE-Development/surf-api/releases/latest)
[](LICENSE)
[](https://kotlinlang.org/)
[](https://openjdk.org/)
[](https://docs.slne.dev/surf-api)
---
## Overview
surf-api is the shared foundation for SLNE's server plugin ecosystem. It provides:
- **Platform-abstracted APIs** for Paper (Bukkit/NMS), Velocity, and Standalone environments
- **Service discovery** via `ServiceLoader` (`requiredService()`) for singleton bridges
- **Component system** with compile-time KSP discovery, topological lifecycle ordering, and
conditional activation
- **NMS bridge pattern** to safely abstract version-specific internals behind stable interfaces
- **Inventory framework DSLs**, command helpers, scoreboard utilities, and extension-rich APIs
- **Gradle plugin** (`surf-api-gradle-plugin`) that configures downstream projects, handles
dependency shading, and runs the KSP processor
---
## Module Structure
```
surf-api
├── surf-api-core # Platform-agnostic core API & implementation
│ ├── surf-api-core # Core API interfaces
│ └── surf-api-core-server # Core implementations
│
├── surf-api-paper # Paper/Bukkit platform
│ ├── surf-api-paper # Public API (extensions, bridges, DSLs)
│ ├── surf-api-paper-server # Implementations (shaded into final JAR)
│ ├── surf-api-paper-nms
│ │ ├── surf-api-paper-nms-common # Shared NMS bridge interfaces
│ │ ├── surf-api-paper-nms-v1-21-11 # NMS impl for 1.21.11
│ │ └── surf-api-paper-nms-v26-1 # NMS impl for 26.1
│ └── surf-api-paper-plugin-test # Local test server (excluded from CI)
│
├── surf-api-velocity # Velocity proxy platform
│ ├── surf-api-velocity # Public API
│ └── surf-api-velocity-server # Implementations
│
├── surf-api-standalone # Standalone (non-server) platform
│
├── surf-api-shared # Cross-platform annotations & component system
│ ├── surf-api-shared-public # Public shared annotations (@ComponentMeta, etc.)
│ └── surf-api-shared-internal # Internal shared utilities
│
├── surf-api-gradle-plugin # Gradle convention plugins & KSP processor
│ └── surf-api-processor # KSP processor — discovers @ComponentMeta at compile time
│
└── surf-api-generator # NMS module scaffolding generator (local only)
```
> **API/Implementation split:** `-api` modules define public interfaces consumed by downstream
> projects. `-server` modules contain implementations that are shaded into the final JAR and never
> exposed as a public API dependency.
---
## Key Concepts
### Service Discovery
Two mechanisms are available depending on the use case:
#### 1. `requiredService()` — Singleton bridges
For singleton platform bridges and NMS abstractions. Backed by Java `ServiceLoader`; implementations
register themselves with `@AutoService`.
```kotlin
// In -api: declare the bridge interface with companion delegation
@NmsUseWithCaution
interface SurfBukkitNmsCommonBridge {
fun nextEntityId(): Int
companion object : SurfBukkitNmsCommonBridge by requiredService()
}
// In -server: provide the implementation
@AutoService(SurfBukkitNmsCommonBridge::class)
class SurfBukkitNmsCommonBridgeImpl : SurfBukkitNmsCommonBridge {
init { checkInstantiationByServiceLoader() }
override fun nextEntityId(): Int = TODO()
}
// Usage — callers go through the companion, unaware of the implementation
val id = SurfBukkitNmsCommonBridge.nextEntityId()
```
#### 2. Component System — Lifecycle-managed components
Classes annotated with `@ComponentMeta` (or the meta-annotations `@Service` / `@Repository`) are
discovered at compile-time by the KSP processor, which writes JSON metadata to
`META-INF/surfapi/components/`. At runtime, `ComponentService`:
1. Loads all component metadata
2. Topologically sorts by `@Priority` and `@DependsOnComponent`
3. Checks conditions (`@ConditionalOnProperty`, `@DependsOnPlugin`, `@DependsOnClass`, …)
4. Calls `suspend fun load()` → `enable()` → `disable()` in order
```kotlin
@Service
class MyFeatureService : SurfComponent {
override suspend fun enable() {
// runs after all dependencies are enabled
}
override suspend fun disable() {
// runs in reverse order on shutdown
}
}
```
---
## Getting Started
### Prerequisites
- Java 25 (GraalVM recommended for CI)
- Gradle 8+
### Build
```bash
# Full build (produces shadow JARs with relocated dependencies)
./gradlew build shadowJar
# Build a single module
./gradlew :surf-api-paper:surf-api-paper-server:build
# Publish to local Maven repository
./gradlew publishToMavenLocal
# Run the Paper test server (local only, not available in CI)
./gradlew :surf-api-paper:surf-api-paper-plugin-test:runServer
```
---
## Conventions
### Kotlin
| Convention | Details |
|---|---|
| **Context parameters** | Enabled globally (`-Xcontext-parameters`). Used in inventory DSLs and other scoped builders. |
| **`@InternalSurfApi`** | `@RequiresOptIn` — mark new internal APIs with this annotation. All subprojects opt-in via compiler args. |
| **Coroutines** | All async work uses Kotlin coroutines. Component lifecycle methods are `suspend`. Bukkit uses MCCoroutine (Folia-aware). |
| **Extension functions** | Primary API enrichment pattern; organized in files named `*-extension.kt` or `*-extensions.kt`. |
| **DSL markers** | `@InventoryFrameworkDSL`, `@ItemDsl`, `@PaneMarker` restrict scope in builder DSLs. |
### Logging
Use Google Flogger via the `logger()` helper:
```kotlin
private val log = logger() // FluentLogger.forEnclosingClass()
log.atInfo().log("Server started")
log.atWarning().withCause(e).log("Failed to load component %s", name)
```
### Package Layout
```
dev.slne.surf.api # Root
dev.slne.surf.api.core.api # Core API interfaces
dev.slne.surf.api.core.server # Core implementations
dev.slne.surf.api.paper.api # Paper API (extensions, bridges, DSLs)
dev.slne.surf.api.paper.server # Paper implementations
dev.slne.surf.api.velocity.api # Velocity API
dev.slne.surf.api.velocity.server # Velocity implementations
dev.slne.surf.api.shared.api # Shared annotations & component system
dev.slne.surf.api.libs.* # Relocation target for all shaded dependencies
```
### Dependency Shading
All non-platform dependencies are shaded via Shadow and relocated to `dev.slne.surf.api.libs.*`
(configured via `relocationPrefix` in `gradle.properties`). Platform APIs (Paper, Velocity) remain
`compileOnly`. Relocations are declared in `CommonSurfPlugin` using an infix DSL:
```kotlin
"me.devnatan.inventoryframework" relocatesTo "devnatan.inventoryframework"
```
---
## Notable Dependencies
| Library | Purpose |
|---|---|
| [PacketEvents](https://github.com/retrooper/packetevents) | Packet-level networking abstraction |
| [CommandAPI](https://commandapi.jorel.dev/) | Brigadier-based command framework |
| [MCCoroutine](https://github.com/Shynixn/MCCoroutine) (SLNE fork) | Folia-aware coroutine dispatching |
| [Inventory Framework](https://github.com/devnatan/inventory-framework) | GUI/inventory DSL |
| [Adventure](https://docs.advntr.net/) | Text & component API |
| [LuckPerms](https://luckperms.net/) | Permissions API |
| [PlaceholderAPI](https://github.com/PlaceholderAPI/PlaceholderAPI) | Placeholder support |
| [Caffeine](https://github.com/ben-manes/caffeine) | High-performance caching |
| [Flogger](https://google.github.io/flogger/) | Fluent logging |
| [Ktor](https://ktor.io/) | HTTP client |
| [Configurate](https://github.com/SpongePowered/Configurate) | Configuration loading |
| [KSP](https://github.com/google/ksp) | Compile-time component discovery |
| [AutoService](https://github.com/google/auto/tree/main/service) | `ServiceLoader` registration |
---
## Contributing
When making changes:
- **API changes** go in `-api` modules. **Never** expose `-server` types in the public API.
- **Implementations** go in `-server` modules.
- **New components**: annotate with `@ComponentMeta` / `@Service` / `@Repository` and implement the
appropriate lifecycle methods.
- **New NMS bridges**: declare the interface in `-api`, implement in `-server`, register via
`@AutoService`, and call `checkInstantiationByServiceLoader()` in the `init` block.
- Publishing is automated — push to a `version/*` branch to trigger a release.
---
## License
This project is licensed under the [GNU General Public License v3.0](LICENSE).
---
## Links
- 📖 [Documentation](https://docs.slne.dev/surf-api)
- 📦 [Releases](https://github.com/SLNE-Development/surf-api/releases)
- 🐛 [Issues](https://github.com/SLNE-Development/surf-api/issues)
- 💬 [Discussions](https://github.com/SLNE-Development/surf-api/discussions)