import com.nixxcode.jvmbrotli.enc.BrotliOutputStream
import com.nixxcode.jvmbrotli.enc.Encoder
import groovy.json.JsonSlurper
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackDevtool
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.zip.GZIPOutputStream
val isDevMode = (configFile["isDevMode"] as? Boolean) ?: false
-repositories {
- mavenCentral()
- maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
+val configureOutput: KotlinJsBrowserDsl.(name: String) -> Unit = { name ->
+ val fileName = "$name.js"
+
+ commonWebpackConfig {
+ outputFileName = fileName
+ if (isDevMode) {
+ mode = KotlinWebpackConfig.Mode.DEVELOPMENT
+ devtool = WebpackDevtool.SOURCE_MAP
+ sourceMaps = true
+ } else {
+ mode = KotlinWebpackConfig.Mode.PRODUCTION
+ devtool = null
+ sourceMaps = false
+ }
+ }
+
+ webpackTask {
+ mainOutputFileName.set(fileName)
+ if (isDevMode) {
+ mode = KotlinWebpackConfig.Mode.DEVELOPMENT
+ devtool = WebpackDevtool.SOURCE_MAP
+ sourceMaps = true
+ } else {
+ mode = KotlinWebpackConfig.Mode.PRODUCTION
+ sourceMaps = false
+ }
+ }
}
-kotlin {
- js("map") {
+val jsTarget: KotlinMultiplatformExtension.(name: String) -> Unit = { name ->
+ js(name) {
browser {
- commonWebpackConfig {
- outputFileName = "map.js"
- if (isDevMode) {
- mode = KotlinWebpackConfig.Mode.DEVELOPMENT
- devtool = WebpackDevtool.SOURCE_MAP
- sourceMaps = true
- } else {
- mode = KotlinWebpackConfig.Mode.PRODUCTION
- devtool = null
- sourceMaps = false
- }
- }
-
- webpackTask {
- mainOutputFileName.set("map.js")
- if (isDevMode) {
- mode = KotlinWebpackConfig.Mode.DEVELOPMENT
- devtool = WebpackDevtool.SOURCE_MAP
- sourceMaps = true
- } else {
- mode = KotlinWebpackConfig.Mode.PRODUCTION
- sourceMaps = false
- }
- }
+ configureOutput(name)
}
binaries.executable()
}
+}
+
+repositories {
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
+}
+
+kotlin {
+ jsTarget("map")
+ jvmToolchain(17)
jvm {
withJava()
}
sourceSets {
+ all {
+ languageSettings {
+ optIn("kotlin.RequiresOptIn")
+ enableLanguageFeature("ContextReceivers")
+ }
+ }
+
val commonMain by getting
val mapMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
- implementation("org.jetbrains.kotlinx:kotlinx-html:0.10.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-html-js:0.10.1")
}
}
java {
toolchain {
- languageVersion.set(JavaLanguageVersion.of(14))
- }
-}
-
-kotlin {
- jvmToolchain(14)
-}
-
-tasks.withType<KotlinCompile> {
- kotlinOptions {
- jvmTarget = "14"
- freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn", "-Xcontext-receivers")
+ languageVersion.set(JavaLanguageVersion.of(17))
}
}
mainClass.set("info.mechyrdia.Factbooks")
}
-tasks.withType<ShadowJar> {
- val mapWebpackTask = tasks.getByName<KotlinWebpack>("mapBrowserProductionWebpack")
- dependsOn(mapWebpackTask)
+val browserWebpackSuffix = if (isDevMode) "BrowserDevelopmentWebpack" else "BrowserProductionWebpack"
+
+val copyToAssets: Task.(name: String, destSubDir: String, destFileName: String) -> Unit = { name, destSubDir, destFileName ->
+ val webpackTask = tasks.getByName<KotlinWebpack>("$name$browserWebpackSuffix")
+ dependsOn(webpackTask)
doFirst {
val assetsDirPath = configFile["assetDir"]?.let { "$it" }
?: "../assets"
val assetsDir = File(rootDir, assetsDirPath)
- val destMapJsName = "main.js"
+ val destJsName = "$destFileName.js"
- val mapJsFile = mapWebpackTask
+ val jsFile = webpackTask
.mainOutputFile
.get()
.asFile
- val mapJsText = mapJsFile.readText()
- val mapJsMapName = "${mapWebpackTask.mainOutputFileName.get()}.map"
- val sourceMapReplaceText = "//# sourceMappingURL=$mapJsMapName"
- val sourceMapReplacement = "//# sourceMappingURL=${destMapJsName}.map"
+ val jsText = jsFile.readText()
+ val jsMapName = "${webpackTask.mainOutputFileName.get()}.map"
+ val sourceMapReplaceText = "//# sourceMappingURL=$jsMapName"
+ val sourceMapReplacement = "//# sourceMappingURL=$destJsName.map"
- val destMapJsFile = File(assetsDir, "map/$destMapJsName")
- val destMapJsMapFile = File(assetsDir, "map/${destMapJsName}.map")
+ val destJsFile = File(assetsDir, "$destSubDir/$destJsName")
+ val destJsMapFile = File(assetsDir, "$destSubDir/$destJsName.map")
if (isDevMode) {
- val mapJsMapFile = File(mapJsFile.parentFile, mapJsMapName)
- val mapJsMapText = mapJsMapFile.readText()
+ val jsMapFile = File(jsFile.parentFile, jsMapName)
+ val jsMapText = jsMapFile.readText()
- destMapJsFile.writeText(mapJsText.replace(sourceMapReplaceText, sourceMapReplacement))
- destMapJsMapFile.writeText(mapJsMapText)
+ destJsFile.writeText(jsText.replace(sourceMapReplaceText, sourceMapReplacement))
+ destJsMapFile.writeText(jsMapText)
} else {
- destMapJsFile.writeText(mapJsText.replace(sourceMapReplaceText, ""))
- destMapJsMapFile.delete()
+ destJsFile.writeText(jsText.replace(sourceMapReplaceText, ""))
+ destJsMapFile.delete()
}
}
}
+tasks.withType<ShadowJar> {
+ copyToAssets("map", "map", "main")
+}
+
tasks.withType<JavaExec> {
javaLauncher.set(javaToolchains.launcherFor {
- languageVersion.set(JavaLanguageVersion.of(14))
+ languageVersion.set(JavaLanguageVersion.of(17))
})
}
private fun preparePan(pan: GalaxyMapPan, panPosition: Vector2? = null) {
if (panPosition != null) {
- pan.x = (window.innerWidth / 2) - (panPosition.x.toDouble() * GALAXY_MAP_SIZE_FACTOR)
- pan.y = (window.innerHeight / 2) - (panPosition.y.toDouble() * GALAXY_MAP_SIZE_FACTOR)
+ pan.x = (window.innerWidth * 0.5) - (panPosition.x.toDouble() * GALAXY_MAP_SIZE_FACTOR)
+ pan.y = (window.innerHeight * 0.5) - (panPosition.y.toDouble() * GALAXY_MAP_SIZE_FACTOR)
} else {
pan.x = (window.innerWidth - (galaxyMap.background.size.x.toDouble() * GALAXY_MAP_SIZE_FACTOR)) / 2
pan.y = (window.innerHeight - (galaxyMap.background.size.y.toDouble() * GALAXY_MAP_SIZE_FACTOR)) / 2
element.style.transform = "translate(${pan.x}px, ${pan.y}px)"
}
-var renderJob: Job? = null
+private var renderJob: Job? = null
+
+val isRenderActive: Boolean
+ get() = renderJob != null
private fun setTitle(ptr: MapObjectPtr) {
document.title = when (ptr) {
}
}
-private class SectorMapPan(val camera: PerspectiveCamera, override val sectorId: String, private val sector: SectorMap, private val interSectorLinks: List<InterSectorLinkDestination>, scope: CoroutineScope) : MapPan(scope) {
+private class SectorMapPan(private val camera: PerspectiveCamera, override val sectorId: String, private val sector: SectorMap, private val interSectorLinks: List<InterSectorLinkDestination>, scope: CoroutineScope) : MapPan(scope) {
private val rayCaster = Raycaster()
override fun handleClick(currX: Double, currY: Double): MapObjectPtr? {
private fun CoroutineScope.SectorMapPan(camera: PerspectiveCamera, sectorId: String, sector: SectorMap, interSectorLinks: List<InterSectorLinkDestination>) = SectorMapPan(camera, sectorId, sector, interSectorLinks, this)
-private fun prepareElement(element: HTMLElement) {
+private fun fullscreenElement(element: HTMLElement) {
element.style.width = "100vw"
element.style.height = "100vh"
element.style.position = "fixed"
val glCanvas = document.create.canvas(content = "")
glCanvas.width = (window.innerWidth * window.devicePixelRatio).roundToInt()
glCanvas.height = (window.innerHeight * window.devicePixelRatio).roundToInt()
- prepareElement(glCanvas)
+ fullscreenElement(glCanvas)
addPanEvents(glCanvas, pan)
val glRenderer = WebGLRenderer(configure {
canvas = glCanvas