Kotlin Developer Instructions - HoshiKurama/MCWandsFramework GitHub Wiki

NOTE: Before beginning this section, be sure you have already looked at the README.md!

Kotlin users have first-class support with MCWandsFramework! Furthermore, you gain access to extra framework features only supported with Kotlin.

Gradle

Kotlin users will need to do a bit more work to set up their project.

To get the API ready for use:

  1. Download the API jar file. This can be found in the releases section with every X.0.0 release. The release title will also mention the API.
  2. Drag the API jar into the root project.

build.gradle.kts:

// NOTE: This file does not include code already expected to be here
plugins {
    id("com.github.johnrengelman.shadow") version "7.0.0"  // Shadow Jar for relocating package names and references
    application                                            // Required for Shadow Jar
    java
}

application {
    mainClass.set("path_from_package_to_main_class")        // CHANGE THIS
}

repositories {
    mavenCentral()       // Maven Central is the only required repository (excluding paper/spigot/etc API)
}

dependencies {
    compileOnly(files("Name_Of_API_JAR.jar"))                                    // Dependency for API jar placed in the root project
    compileOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0")       // Dependency for coroutines (OPTIONAL)
}

tasks {
    shadowJar {
        dependencies {
            /* If you are using any other include statements, this line is not necessary. It is ONLY necessary if you lack any other include statements.
               This prevents ShadowJar from shading in all dependencies, which would result in a linkage violation. */
            include(dependency("Placeholder::"))
        }

        /* These rename all matching qualifiers on the left to the qualifier on the right. This is very important so your custom wands use the classes 
           and libraries shaded into the framework plugin. */
        relocate("kotlin", "com.github.hoshikurama.mcwandsframework.shaded.kotlin")
        relocate("kotlinx.coroutines", "com.github.hoshikurama.mcwandsframework.shaded.kotlinx.coroutines")
    }
}

You're now ready to create custom wands!

Service and Registration

Service is provided via the ServicesManager API.

val wandsService: MCWandsService? = Bukkit.getServicesManager().getRegistration(MCWandsService::class.java)?.provider 

Wand behaviour is defined with KotlinWandFunction, a SAM interface. The contained function takes two parameters: a WandData type and a ContextContainer type.

  • WandData - Contains the following properties:
    • player - Player using wand
    • cooldown - Specialty cooldown in seconds
    • intensity - Multi-purpose value representing the strength of the specialty action
    • range - Multi-purpose value representing the range of the specialty action
  • ContextContainer - Holds CoroutineContext objects. This can be ignored unless you need it. Contains the following properties:
    • main - context to run on the main thread
    • async - context for any off-thread in the Bukkit thread-pool
// Example action that tells player hello
val helloKnownPlayer = KotlinWandFunction { params, _ ->
    val player = params.player
    player.sendMessage("Hello, ${player.name}!")
}

Wands are registered using the MCWandsService#registerWandKotlin() member function, which takes a wand name and a KotlinWandFunction object. The function returns a boolean describing if registration was successful or not (when attempted). You cannot register a wand with a name that has already been registered.

// You can define the behaviour at registration...
wandsService?.registerWandKotlin("HelloUnknownPlayer") { params, _ ->
    params.player.sendMessage("Hello, random player!")
}

// ... or you may use other KotlinWandFunction implementations!
wandsService?.registerWandKotlin("HelloKnownPlayer", helloKnownPlayer)

NOTE: Please make sure to list MCWandsFramework as a dependency in your plugin.yml!

Coroutines

A Kotlin-exclusive feature with the framework is native coroutine support. MCWandsFramework utilizes the MCCoroutines library. Users wanting to take advantage of this feature don't have to change much at all!

Users will register their wands the same way as in the previous section and build behaviour with the same KotlinWandFunction SAM interface. This interface's function is actually of type suspend (WandData, ContextContainer) -> Unit, so it's ready for coroutine usage! The function is first called with a context restricted to the main-thread, the same context contained by ContextContainer#main.

val delayedHello = KotlinWandFunction { params, contexts -> 
    coroutineScope {
        params.player.sendMessage("Hello from the main-thread!")
        delay(3000)
        withContext(contexts.async) {
            params.player.sendMessage("And hello from an off-thread!")
        }
    }
}

wandsService?.registerWandKotlin("DelayedHello", delayedHello)