Skip to content

adaliszk/gradle-scaffoldit-modkit

Repository files navigation

Scaffoldit Gradle Plugin

Latest Java Kotlin Gradle License

Keep the necessary boilerplate at the absolute minimum while also having access to a
and flexible toolkit for mod development for Hytale, and later for Minecraft.

Zero-boilerplate Gradle
Configure everything from settings or build, kotlin or groovy.
All toggles exposed
Every argument, every version, is fully exposed for customization.
Batteries included
MavenCentral, CurseMaven, HytaleMaven auto-wired, ready to use!
First-class Hytale support
Fully typed manifest, nested SubPlugins, in-place generation.
Agent-based hot-reload
Runtime mod lifecycle reloads using `DCEVM` for code hot swapping.
Monorepo & multiloader ready
`common {}` + `hytale {}` = automatic workspace linking for multi-workspace use.
Kotlin & Java seamlessly
Java pre-configured, and `useKotlin()` available to switch to Kotlin!
Flat layout support
Skip `main/java/package` path via `useFlat()` without affecting jars.
Gradle tasks
Expose all IDE-style integrations as tasks for CLI usage.
IDEA configuration
Automatic run configuration detection and creation for Hytale.
SDK Resolution
Automatically configure and detect JVMs and turn on DCEVM when possible.
True source linking
DevServer & AssetEditor use your sources; no copy, instant feedback.
Testing included
JUnit or Kotest with coverage reporting out of the box.
Pre-configured devserver
Creative superflat with offline mode turned on for a quick start.
 

Note

Latest update (0.2.9 → 0.2.14):

  • Upgraded to Kotlin 2.3.10
  • Fix quotation usage to IDEA configuration where it is necessary (#12)
  • Separated the Assets.zip resolution to allow builds without it (#18)
  • Separate Toolchain and Project plugins to avoid immutable errors (#13)
  • Fix :setupServer evaluation error (#21)
  • Fix IDEA configuration NPE with multi-module setup (#22)
  • Fix :runServer missing CLI arguments (missing HytaleAssets shutdown)

See the whole CHANGELOG

Requirements

  • IntelliJ IDEA (even Community edition), VS Code, or any other editor
  • Java 25, use JetBrains Runtime (JBR) for hot swapping to work!
  • Hytale installed through the launcher when used as the target

Usage

// settings.gradle.kts
rootProject.name = "dev.example"
plugins {
    id("dev.scaffoldit") version "0.2.+"
}
hytale {
    manifest {
        Group = "ScaffoldIt"
        Name = "Example"
        Main = "dev.example.mod.ExamplePlugin"
        IncludesAssetPack = true
    }
}

This will expose several Gradle commands under the "hytale" group:

Command Description
gradlew setupServer Create the the devserver, delete the folder yourself to make a complete reset!
gradlew runServer Runs the devserver, use -Ddebug for opening a debugger and allow hot-swapping.
gradlew generateManifest Generate the plugin manifest from settings and existing values.

Configuration

Everything is supported in the settings.gradle[.kts], but includes are not possible in build.gradle[.kts] so the recommendation is to configure everything in one file:

common { }

Collects and configures common library packages and adds them to the target projects as dependencies. All include() projects are relative from the common directory. It automatically creates the necessary folder structure but leaves the classes itself to you.

projectDir: String

Configures the parent directory for the common workspaces, by default, it is set to common, reset it with an empty string to simply create all your projects in the repository root.

repositories {}, dependencies {}, include(...projectString), include(projectString)

Exposes the standard dependency management and project declaration where you can share the repos and libraries with all projects and declare any number of groups with their shared repos and dependencies, like:

common {
    dependencies {
        compileOnly("dev.example.project:package:version") // <- Shared with all includes()
    }
    include("one", "two", "three") {
        dependencies {
            compileOnly("dev.example.project:package:version") // <- Shared with the include group
        }
    }
    include("four") // <- one, two, three automatically added here!
}

useKotlin(dependencyString)

Use and specify the Kotlin STDLib for compilation, left alone it will import the standard org.jetbrains.kotlin:kotlin-stdlib but you can specify your own version, such as anything already distributed on the curse maven.

This function sets the kotlin: String? property, so if you prefer, you can also simply assign your stdlib using kotlin = "my.kotlin.srdlib".

useFlat()

Switch the directory layout to flat that drops main/com/example/project, this is useful for Kotlin as it reduces the complexity of the project structure and the compiler still re-creates that within your built jar file.

hytale { }

Configures a hytale project with dependencies, manifest management, and inherits common packages when they are declared. It automatically creates the necessary folder structure but leaves the classes itself to you.

projectDir: String

Configures the parent directory for the hytale workspaces, by default, it is set to hytale, reset it with an empty string to simply create all your projects in the repository root.

usePatchline(String), useVersion(String)

Configure which patchline from maven to depend on and within that which version. By default, it will use the RELEASE patchline with the "+" version, which means the latest.

devserver {}

  • Enabled: Boolean: Controls if the devserver should be generated at all. (default=true)
  • AllowOp: Boolean: Enables privileged server sessions for OP permissions. (default=true)
  • DisableSentry: Boolean: Avoids spamming Hypixel with modding errors. (default=true)
  • AcceptEarlyPlugins: Boolean: Sets your plugin to be loaded with the builtins (default=false)
  • IncludeUserMods: Boolean: Links the launcher global mods into the devserver (default=false)

repositories {}, dependencies {}, include(...projectString), include(projectString)

Exposes the standard dependency management and project declaration where you can share the repos and libraries with all projects and declare any number of groups with their shared repos and dependencies, like:

hytale {
    dependencies {
        compileOnly("dev.example.project:package:version") // <- Shared with all includes()
    }
    include("one", "two", "three") {
        dependencies {
            compileOnly("dev.example.project:package:version") // <- Shared with the include group
        }
    }
    include("four") // <- one, two, three automatically added here!
}

useKotlin(dependencyString)

Use and specify the Kotlin STDLib for compilation, left alone it will import the standard org.jetbrains.kotlin:kotlin-stdlib but you can specify your own version, such as anything already distributed on the curse maven.

This function sets the kotlin: String? property, so if you prefer, you can also simply assign your stdlib using kotlin = "my.kotlin.srdlib".

useFlat()

Switch the directory layout to flat that drops main/com/example/project, this is useful for Kotlin as it reduces the complexity of the project structure and the compiler still re-creates that within your built jar file.

manifest { }

  • Group: String: Group identifier, typically the organization in one PascalCase word.
  • Name: String: Plugin name, typically in one PascalCase word, displayed in the mods list.
  • Version: String: Semantic version ("1.0.0"), displayed in the most list with the "v" prefix.
  • Description: String?: Optional field, not shown anywhere for now.
  • Author: List<Author>?: The .Name used to show in the mods list "by ..." section.
  • Website: String?: Optional field, not shown anywhere for now.
  • DisabledByDefault: Boolean: Controls if the plugin is loaded at startup or not.
  • IncludesAssetPack: Boolean: Flags the plugin for loading and watching assets.
  • Dependencies: Map<Group:Name, VersionRange>?: What needs to "SETUP" with your plugin.
  • OptionalDependencies: Map<Group:Name, VersionRange>?: What needs exist but no matter what state.
  • LoadBefore: Map<Group:Name, VersionRange>?: Moves your plugin to load before the first of these.
  • ServerVersion: String: Server Version, e.g., "1.0.0".
  • Main: String: Your main class full name to be loaded from classpath.
  • SubPlugins: List<HytaleManifest>?: Same manifest as above to configure any sub-plugins.

Where the Author accepts:

  • Name: String: the display name shown in the mods list.
  • Website: String?: Optional field, not shown anywhere for now.
  • Email: String?: Optional field, not shown anywhere for now.

Hot Swapping

To enable dynamic class reloading at runtime, you MUST use a JetBrains JRE, which is available for free at https://github.com/JetBrains/JetBrainsRuntime, or you can manage it within the IDEA SDK window. Once configured, update your run configuraitons to use it and watch for the Gradle widget in your code section's top right corner.

Scaffoldit also ships Agent Plugin that at runtime detects the Hot Swapping and reloads plugins automatically for you; with that you only need to click on "Code Changed" in the editor UI. If you only need this agent, you can use it by adding:

dependencies {
    runtimeOnly("dev.scaffoldit:devtools:0.2.+")
}

Note

You only need this if you do not use the ScaffoldIt Plugin itself!

Under the hood toggles

While the plugin sets up a complete development environment, you can fine-tune that by setting the included package versions, and their feature flags in the gradle.properties:

# gradle.properties
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m
# Use these after you stop touching your settings:
org.gradle.configuration-cache=true
org.gradle.caching=true
# Under the hood settings:
env.java.version=25
env.java.compileSources=true
env.java.compileDocs=false
env.scaffoldit.kotlinSupport=true
env.scaffoldit.kotlinTest=true
env.scaffoldit.kotlinTest.version=6.1.1
env.scaffoldit.javaUnitTest=true
env.scaffoldit.javaUnitTest.version=5.10.1
env.scaffoldit.jacocoCoverage=true
env.scaffoldit.autoToolchain=true
env.scaffoldit.monorepoSupport=true
env.scaffoldit.monorepoAutoDepends=true
env.scaffoldit.globalAssets=true
env.hytale.devServerDCEVM=true
env.hytale.devServerHotReload=true
env.hytale.manifestGenerator=true
env.hytale.configureIdea=true
# Example: D:\\HYTALE\\Data
hytale.home_path=""

Troubleshooting

Assets are not present, without that it is not possible to run a server!

Add or Edit your gradle.properties file with the hytale.home_path= option pointing towards your installation folder that contains the install path. For example: D:/HYTALE/Data.

Could not target platform: '...' using tool chain: '...'.

Check that Java 25 is installed and configured under File → Project Structure → SDKs, use JetBrains Runtimeis, or any other DVEVM enabled runtime. You may also need to edit the project:devserver run configuration and choose your project default or JBR.

After a code change, the Hot-reload does not reload your plugin.

With IDEA, verify that you are using the generated project:devserver run configuration in DEBUG mode. With any other, verify that the :runServer task does have a -Ddebug flag and the used JDK is JetBrains Runtime, or any other DCEVM enabled runtime.

Devserver has not been initialized in ... yet

Run the :setupServer task to create a fresh devserver folder.

Skipping pack at ...: missing or invalid manifest.json

[Universe|P] Failed to setup plugin Hytale:...

Check if you use any registration or dependency to Hytale plugins in your setup() function without depending on the Hytale plugin in your manifest.json. Add any that you found missing to ensure the development plugin loads in the right order.

Contributions

Feel free to open issues or pull requests if you have some problems, you can also reach out to me on discord under the nickname of kicsivazz.

About

Gradle Plugin to build mods for Hytale with delegations to _create_ easy to assemble components to apply in a monorepo style.

Topics

Resources

License

Stars

Watchers

Forks

Contributors