Skip to content

Commit

Permalink
More messing with classloaders
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Jan 25, 2024
1 parent b52d90c commit 85a3420
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 28 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies {
library(kotlin("scripting-common"))
library(kotlin("scripting-jvm"))
library(kotlin("scripting-jvm-host"))
library(kotlin("script-runtime"))

compileOnly("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT")
compileOnly("com.github.Slimefun:Slimefun4:RC-36")
Expand Down Expand Up @@ -49,7 +50,6 @@ tasks.shadowJar {

dependencies {
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib"))
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk8"))
}
}

Expand Down
20 changes: 17 additions & 3 deletions src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.github.addoncommunity.galactifun

import io.github.addoncommunity.galactifun.api.objects.planet.PlanetaryWorld
import io.github.addoncommunity.galactifun.base.BaseUniverse
import io.github.addoncommunity.galactifun.scripting.PlanetScript
import io.github.addoncommunity.galactifun.scripting.evalScript
import io.github.seggan.kfun.AbstractAddon
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion
Expand All @@ -26,20 +28,25 @@ class Galactifun2 : AbstractAddon() {

var shouldDisable = false
if (!PaperLib.isPaper()) {
log(Level.SEVERE, "Galactifun only supports Paper and its forks (e.x. Airplane and Purpur)")
log(Level.SEVERE, "Galactifun2 only supports Paper and its forks (e.x. Airplane and Purpur)")
log(Level.SEVERE, "Please use Paper or a fork of Paper")
shouldDisable = true
}
if (Slimefun.getMinecraftVersion().isBefore(MinecraftVersion.MINECRAFT_1_19)) {
log(Level.SEVERE, "Galactifun only supports Minecraft 1.19 and above")
log(Level.SEVERE, "Galactifun2 only supports Minecraft 1.19 and above")
log(Level.SEVERE, "Please use Minecraft 1.19 or above")
shouldDisable = true
}
if (Bukkit.getPluginManager().isPluginEnabled("ClayTech")) {
log(Level.SEVERE, "Galactifun will not work properly with ClayTech")
log(Level.SEVERE, "Galactifun2 will not work properly with ClayTech")
log(Level.SEVERE, "Please disable ClayTech")
shouldDisable = true
}
if (Bukkit.getPluginManager().isPluginEnabled("Galactifun")) {
log(Level.SEVERE, "Galactifun2 will not work properly with Galactifun")
log(Level.SEVERE, "Please remove Galactifun")
shouldDisable = true
}

if (shouldDisable) {
Bukkit.getPluginManager().disablePlugin(this)
Expand Down Expand Up @@ -72,6 +79,13 @@ class Galactifun2 : AbstractAddon() {
val returnValue = result.valueOrThrow().returnValue
if (returnValue is ResultValue.Error) {
throw returnValue.error
} else {
for (planet in (returnValue.scriptInstance as PlanetScript).toRegister) {
if (planet is PlanetaryWorld) {
planet.register()
}
log("Registered planet: ${planet.name}")
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.addoncommunity.galactifun.api.objects.properties.atmosphere

import org.bukkit.World
import java.util.EnumMap
import java.util.*

@AtmosphereDsl
class AtmosphereBuilder internal constructor() {
Expand All @@ -20,11 +20,11 @@ class AtmosphereBuilder internal constructor() {
this@AtmosphereBuilder.composition[gas] = this
}
}
}

fun composition(builder: CompositionBuilder.() -> Unit) {
val compositionBuilder = CompositionBuilder()
builder(compositionBuilder)
}
fun AtmosphereBuilder.composition(builder: AtmosphereBuilder.CompositionBuilder.() -> Unit) {
val compositionBuilder = CompositionBuilder()
builder(compositionBuilder)
}

@DslMarker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object WorldManager {
private val defaultConfig: YamlConfiguration

init {
val configFile = File("plugins/Galactifun", "worlds.yml")
val configFile = File(pluginInstance.dataFolder, "worlds.yml")
config = YamlConfiguration()
defaultConfig = YamlConfiguration()
config.setDefaults(defaultConfig)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
package io.github.addoncommunity.galactifun.scripting

import io.github.addoncommunity.galactifun.api.objects.TheUniverse
import io.github.addoncommunity.galactifun.api.objects.planet.PlanetaryObject
import io.github.addoncommunity.galactifun.api.objects.properties.DayCycle
import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.Atmosphere
import io.github.addoncommunity.galactifun.base.BaseUniverse
import io.github.addoncommunity.galactifun.base.objects.earth.Earth
import io.github.addoncommunity.galactifun.base.objects.earth.Moon
import io.github.addoncommunity.galactifun.pluginInstance
import org.bukkit.Material
import org.bukkit.World
import kotlin.reflect.KClass
import kotlin.script.experimental.annotations.KotlinScript
import kotlin.script.experimental.api.*
import kotlin.script.experimental.jvm.baseClassLoader
import kotlin.script.experimental.jvm.dependenciesFromClassloader
import kotlin.script.experimental.jvm.jvm
import kotlin.script.experimental.jvm.jvmTarget
import kotlin.script.experimental.host.ScriptingHostConfiguration
import kotlin.script.experimental.host.getScriptingClass
import kotlin.script.experimental.jvm.*
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
import kotlin.script.experimental.jvmhost.createJvmCompilationConfigurationFromTemplate
import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTemplate

@KotlinScript(
fileExtension = "planet.kts",
compilationConfiguration = PlanetScriptConfig::class,
evaluationConfiguration = PlanetScriptEval::class
evaluationConfiguration = PlanetScriptEval::class,
hostConfiguration = PlanetScriptHost::class
)
abstract class PlanetScript {
val eternalDay = DayCycle.ETERNAL_DAY
val eternalNight = DayCycle.ETERNAL_NIGHT

val toRegister = mutableListOf<PlanetaryObject>()
}

object PlanetScriptConfig : ScriptCompilationConfiguration({
Expand All @@ -35,7 +41,13 @@ object PlanetScriptConfig : ScriptCompilationConfiguration({
"kotlin.time.Duration.Companion.hours",
"kotlin.time.Duration.Companion.days"
)
defaultImports(Material::class, BaseUniverse::class, TheUniverse::class, Earth::class, Moon::class)
defaultImports(
Material::class,
BaseUniverse::class,
TheUniverse::class,
Atmosphere::class,
World.Environment::class
)
compilerOptions.append("-Xadd-modules=ALL-MODULE-PATH")
jvm {
dependenciesFromClassloader(classLoader = pluginInstance::class.java.classLoader, wholeClasspath = true)
Expand All @@ -49,6 +61,37 @@ object PlanetScriptEval : ScriptEvaluationConfiguration({
}
})

object PlanetScriptHost : ScriptingHostConfiguration({
getScriptingClass(object : GetScriptingClassByClassLoader {
override fun invoke(
classType: KotlinType,
contextClassLoader: ClassLoader?,
hostConfiguration: ScriptingHostConfiguration
): KClass<*> {
val cl = pluginInstance::class.java.classLoader
val fromClass = classType.fromClass
if (fromClass != null) {
if (fromClass.java.classLoader == null) return fromClass // root classloader
val actualClassLoadersChain = generateSequence(cl) { it.parent }
if (actualClassLoadersChain.any { it == fromClass.java.classLoader }) return fromClass
}
return try {
pluginInstance::class.java.classLoader.loadClass(classType.typeName).kotlin
} catch (e: Throwable) {
throw IllegalArgumentException("unable to load class ${classType.typeName}", e)
}
}

override fun invoke(
classType: KotlinType,
contextClass: KClass<*>,
hostConfiguration: ScriptingHostConfiguration
): KClass<*> = invoke(classType, contextClass.java.classLoader, hostConfiguration)
})
})

fun evalScript(script: SourceCode): ResultWithDiagnostics<EvaluationResult> {
return BasicJvmScriptingHost().eval(script, PlanetScriptConfig, PlanetScriptEval)
val compileConfig = createJvmCompilationConfigurationFromTemplate<PlanetScript>(PlanetScriptHost)
val evalConfig = createJvmEvaluationConfigurationFromTemplate<PlanetScript>(PlanetScriptHost)
return BasicJvmScriptingHost().eval(script, compileConfig, evalConfig)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import io.github.addoncommunity.galactifun.api.objects.planet.PlanetaryObject
import io.github.addoncommunity.galactifun.api.objects.planet.PlanetaryWorld
import io.github.addoncommunity.galactifun.api.objects.properties.DayCycle
import io.github.addoncommunity.galactifun.api.objects.properties.Orbit
import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.Atmosphere
import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.AtmosphereBuilder
import io.github.addoncommunity.galactifun.scripting.PlanetDsl
import io.github.addoncommunity.galactifun.scripting.PlanetScript
import io.github.addoncommunity.galactifun.scripting.RequiredProperty
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.World
import org.bukkit.inventory.ItemStack
import kotlin.time.Duration

Expand All @@ -20,28 +25,45 @@ class PlanetBuilder {
var orbit: Orbit by RequiredProperty()
var dayCycle: DayCycle by RequiredProperty()

var atmosphere = Atmosphere.NONE
var world: String? = null

fun build(): PlanetaryObject {
return object : PlanetaryObject(name, ItemStack(item)) {
override val dayCycle = this@PlanetBuilder.dayCycle
override val orbiting = this@PlanetBuilder.orbiting
override val orbit = this@PlanetBuilder.orbit
val world = this.world
if (world != null) {
return object : PlanetaryWorld(name, ItemStack(item)) {
override val dayCycle = this@PlanetBuilder.dayCycle
override val orbiting = this@PlanetBuilder.orbiting
override val orbit = this@PlanetBuilder.orbit
override val atmosphere = this@PlanetBuilder.atmosphere

override fun loadWorld(): World = Bukkit.getWorld(world) ?: error("World $world does not exist")
}
} else {
return object : PlanetaryObject(name, ItemStack(item)) {
override val dayCycle = this@PlanetBuilder.dayCycle
override val orbiting = this@PlanetBuilder.orbiting
override val orbit = this@PlanetBuilder.orbit
}
}
}

val Duration.long: DayCycle
get() = DayCycle(this)
}

inline fun planet(block: PlanetBuilder.() -> Unit): PlanetaryObject {
inline fun PlanetScript.planet(block: PlanetBuilder.() -> Unit): PlanetaryObject {
val planet = PlanetBuilder().apply(block).build()
if (planet is PlanetaryWorld) {
planet.register()
}
toRegister.add(planet)
return planet
}

inline fun PlanetBuilder.orbit(block: OrbitBuilder.() -> Unit) {
orbit = OrbitBuilder().apply(block).build()
}

fun PlanetBuilder.eternal(ticks: Int): DayCycle = DayCycle.eternal(ticks)
fun PlanetBuilder.eternal(ticks: Int): DayCycle = DayCycle.eternal(ticks)

fun PlanetBuilder.atmosphere(block: AtmosphereBuilder.() -> Unit) {
atmosphere = Atmosphere.buildAtmosphere(block)
}

0 comments on commit 85a3420

Please sign in to comment.