Getting Started

This guide takes you from zero to a working datapack using Kore and Kotlin. It also highlights a few Kotlin/Kore tips that Java beginners often miss.

Prerequisites

  • Java 21 (JDK 21) or higher
  • Kotlin + Gradle (using the Gradle wrapper is recommended)
  • An IDE with Kotlin support (IntelliJ IDEA recommended)
  • Basic knowledge of Minecraft datapacks will help you.

The fastest way to start is the Kore Template repository. It's preconfigured and ready to run.

The template already sets Java 21 and enables the required Kotlin options.

Option B: Add Kore to an existing project

Add the dependency to your build file.

Gradle (Kotlin)

dependencies {
  implementation("io.github.ayfri.kore:kore:VERSION")
}
Kotlin

Gradle (Groovy)

dependencies {
  implementation 'io.github.ayfri.kore:kore:VERSION'
}
Groovy

Maven

<dependency>
  <groupId>io.github.ayfri.kore</groupId>
  <artifactId>kore</artifactId>
  <version>VERSION</version>
</dependency>
XML

Amper

dependencies:
  - io.github.ayfri.kore:kore:VERSION
YAML

Kotlin configuration

Enable context receivers (parameters) and set Java toolchain in your build.gradle.kts:

kotlin {
	compilerOptions {
		freeCompilerArgs.add("-Xcontext-parameters")
	}

	jvmToolchain(21)
}
Kotlin

Your first datapack (Hello, Kore)

Create a Main.kt and paste:

fun main() {
	val datapack = dataPack("hello_kore") {
		function("display_text") {
			tellraw(allPlayers(), textComponent("Hello Kore!"))
		}

		pack {
			description = textComponent("Hello Kore datapack")
		}
	}

	// Generate a zip you can drop in your world's datapacks folder
	datapack.generateZip()
	// Alternatively, generate files in a folder: datapack.generate()
}
Kotlin
  • Run main from your IDE.
  • A datapack archive is produced; put it into your Minecraft world's datapacks/ folder.
  • In-game, run: /function hello_kore:display_text.

Tips for Kotlin newcomers

  • Null safety: Kotlin's type system distinguishes nullable and non-nullable types. Use ? for nullable types and prefer safe calls ( ?.) and the Elvis operator (?:). See Null Safety.
val name: String? = System.getenv("USER")
val length: Int = name?.length ?: 0 // safe call + default when null
Kotlin
  • Type inference: You rarely need to specify types explicitly-Kotlin infers them for you. Use val for read-only variables and var for mutable ones. Prefer val for immutability.
val count = 0 // Int inferred
var title = "Hello" // String inferred
// Prefer val; use var only when you need to reassign
Kotlin
  • Smart casts: The compiler automatically casts types after checks (e.g., if (x is String) { x.length }).
fun lengthIfString(x: Any): Int = if (x is String) x.length else 0
Kotlin
  • Extension functions: Add new functions to existing types without inheritance. Kore uses this for DSLs. See Extensions.
fun String.titleCase(): String = replaceFirstChar { it.titlecase() }
// Usage: "kore".titleCase() -> "Kore"
Kotlin
val names = listOf("Alex", "Steve", "Sam")
val shout = names.map { it.uppercase() }.filter { it.startsWith("S") }
Kotlin
  • DSLs + context receivers: Inside dataPack { ... }, many builders are available without qualifiers. The compiler flag -Xcontext-parameters is required.
  • Extract helpers with extensions: Attach utilities to DataPack to keep code organized:
fun DataPack.myBasics() = function("setup") {
	// your setup
}

fun main() = dataPack("my_pack") {
	myBasics()
}
Kotlin
  • Name collisions in builders: Some builder names exist in multiple contexts (e.g., nbt, predicate). If your IDE auto-imports the wrong symbol, qualify with this. inside the DSL scope to target the correct function, or fix the import. Example:
predicate("my_function") {
	this.nbt("my_nbt") { /* ... */ } // Use this to correctly import nbt()
}
Kotlin

Then just remove this. now that you know the import is correct.

  • Idempotency: Declaring the same record twice is safe, Kore only keeps the last one.

  • Kotlin Playground: Try out code online at play.kotlinlang.org.

  • Official docs: The Kotlin documentation is excellent for learning language features and best practices.

Project layout and outputs

  • Your code lives under src/main/kotlin (template already set).
  • Generated datapacks: .generate() writes a folder; .generateZip() writes a zip; .generateJar() targets mod loaders.
  • During development, enable pretty JSON in Configuration to inspect outputs.
  • Split your code into multiple files to keep things organized.

Troubleshooting

  • Unresolved DSL symbols: Ensure the Kore dependency is on the classpath and -Xcontext-parameters is enabled.
  • Java version errors: Verify jvmToolchain(21) and that your JDK is 21.
  • Dev loop: Re-run your program after edits to regenerate the datapack.

Essential pages for new users:

For the full documentation index, see Home.

See also