Skip to main content

Overview

Oyasai Server Platform uses Gradle 9 with Kotlin DSL for building all plugins. The build system is integrated with Nix for reproducible builds and dependency management.

Gradle Configuration

Build System Components

  • Gradle Version: 9 (provided via Nix)
  • JDK: Temurin 25
  • Build Language: Kotlin DSL (.gradle.kts files)
  • Plugins: Kotlin JVM, Shadow (fat JAR creation)

Project Structure

platform/
├── build.gradle.kts         # Root build configuration
├── settings.gradle.kts      # Multi-project setup
├── gradle.lock             # Nix dependency lockfile
├── gradle/                 # Gradle wrapper files
└── plugins/                # All plugin subprojects
    ├── OyasaiUtilities/
    │   └── build.gradle.kts
    └── DynamicProfile/
        └── build.gradle.kts

Root Build Configuration

The root build.gradle.kts configures all plugin subprojects automatically.

Buildscript Dependencies

buildscript {
  dependencies {
    classpath(libs.kotlin.plugin)
    classpath(libs.shadow.plugin)
  }
  repositories { mavenCentral() }
}
See build.gradle.kts:3-10.

Repository Configuration

All projects have access to these repositories:
allprojects {
  repositories {
    mavenCentral()
    maven("https://repo.purpurmc.org/snapshots")
    maven("https://nexus.frengor.com/repository/public/")
    maven("https://nexus.scarsz.me/content/groups/public/")
  }
}
See build.gradle.kts:12-19.

Subproject Configuration

Every plugin under :plugins:* automatically receives:
  1. Applied Plugins:
    • org.jetbrains.kotlin.jvm
    • com.gradleup.shadow
    • java-library
  2. JAR Configuration:
    • Default JAR task is disabled
    • Shadow JAR is used for all builds
    • No classifier (clean filenames)
    • Duplicate strategy: EXCLUDE
  3. Resource Processing:
    • Version property expansion in plugin.yml
    • UTF-8 charset for filtering
  4. Build Task:
    • Depends on shadowJar task
See build.gradle.kts:21-53.

Common Gradle Tasks

Build Tasks

gradle build --parallel

Shadow JAR Tasks

gradle shadowJar --parallel

Dependency Tasks

gradle :plugins:OyasaiUtilities:dependencies

Project Information

gradle projects

Plugin Build Files

Minimal build.gradle.kts

Most plugins only need to declare dependencies:
dependencies {
  compileOnly(libs.purpur.api)
}
Example from plugins/OyasaiUtilities/build.gradle.kts:1-5.

With Multiple Dependencies

dependencies {
  compileOnly(libs.purpur.api)
  compileOnly(libs.vault.api)
  implementation("com.google.code.gson:gson:2.10.1")
}

With Kotlin Standard Library

dependencies {
  compileOnly(libs.purpur.api)
  implementation(kotlin("stdlib"))
}

Nix Integration

gradle2nix

Oyasai Platform uses gradle2nix for reproducible Nix builds. When you add or update dependencies, you must regenerate the lockfile.

Update Lockfile

gradle2nix
This command:
  1. Resolves all Gradle dependencies
  2. Generates gradle.lock for Nix
  3. Ensures reproducible builds
Always run gradle2nix after modifying dependencies in any build.gradle.kts file. The CI will fail if the lockfile is out of sync.

Nix Build Process

The Nix build system builds all plugins in a single batch:
plugins-batch = scopeSelf.gradle2nix.buildGradlePackage {
  pname = "plugins";
  version = "0.0.0";
  src = # ... filtered source files
  gradle = scopeSelf.gradle;
  buildJdk = scopeSelf.jdk;
  lockFile = ../gradle.lock;
  gradleBuildFlags = [ "build" ];
  installPhase = '''
    mkdir -p $out
    cp plugins/*/build/libs/*.jar $out
  ''';
};
See nix/oyasai-scope.nix:50-76.

Individual Plugin Derivations

Each plugin gets a thin derivation that copies from the batch build:
plugins = lib.mapAttrs' (
  name: _:
  lib.nameValuePair (lib.toLower name) (
    pkgs.runCommand name { } '''
      mkdir -p $out
      cp ${plugins-batch}/${name}.jar $out
    '''
  )
) (builtins.readDir ../plugins);
See nix/oyasai-scope.nix:106-114.

Version Management

Setting Version

The version is set at the project level and automatically expanded in plugin.yml:
name: MyPlugin
version: ${version}
main: com.oyasai.myplugin.MyPlugin
The ${version} placeholder is replaced during the processResources task (see build.gradle.kts:44-49).

Version in Nix

When creating server packages, you can reference plugins by version:
plugins = with (oyasai-plugin-registry.forVersion version); [
  essentialsx
  fastasyncworldedit
];

Build Performance

Parallel Builds

Always use --parallel for multi-plugin builds:
gradle build --parallel

Gradle Daemon

The Gradle daemon speeds up subsequent builds. It’s enabled by default in Nix devshell.

Build Cache

Gradle’s build cache is automatically configured. Incremental builds reuse unchanged outputs.

CI Builds

The CI runs:
nix flake check -L
This builds all packages and runs tests. See CONTRIBUTING.md:46-50.

Troubleshooting

Clean Build

If you encounter build issues:
gradle clean build

Refresh Dependencies

Force Gradle to re-download dependencies:
gradle build --refresh-dependencies

Check Lockfile Sync

If Nix builds fail but Gradle builds succeed:
gradle2nix
git diff gradle.lock

Gradle Wrapper Issues

In the Nix devshell, use the provided Gradle:
which gradle  # Should point to Nix store
gradle --version

Next Steps

Plugin Development

Learn how to create and build plugins

Nix Packages

Create server configurations with Nix

Testing

Test your plugins locally

Contributing

Submit your changes for review

Build docs developers (and LLMs) love