Skip to content

Commit

Permalink
Added NeoForge support, Kotlin 2.0.0, .minecraft is no longer used
Browse files Browse the repository at this point in the history
  • Loading branch information
ya-ilya committed Jun 10, 2024
1 parent df40296 commit 7ed7d64
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 67 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ bin/
### Mac OS ###
.DS_Store

### Kotlin ###
.kotlin

### kraftia ###
krafita-api/kraftia
kraftia-headless/kraftia
3 changes: 1 addition & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ org.gradle.caching=true

# kotlin
kotlin.code.style=official
kotlin.experimental.tryK2=true
kotlinVersion=1.9.10
kotlinVersion=2.0.0

# kraftia
kraftiaVersion=0.2
Expand Down
26 changes: 8 additions & 18 deletions kraftia-api/src/main/kotlin/org/kraftia/api/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.kraftia.api.version.Version
import org.kraftia.api.version.downloader.DownloaderProgress.Companion.downloaderProgress
import org.kraftia.api.version.downloader.downloaders.FabricVersionDownloader
import org.kraftia.api.version.downloader.downloaders.ForgeVersionDownloader
import org.kraftia.api.version.downloader.downloaders.NeoForgeVersionDownloader
import org.kraftia.api.version.downloader.downloaders.VersionDownloader
import org.kraftia.api.version.serializers.ArgumentSerializer
import java.io.File
Expand All @@ -38,7 +39,6 @@ object Api {
val operatingSystem = OperatingSystem.current
val launcherDirectory: Path = path("kraftia")
val instancesDirectory: Path = path(launcherDirectory, "instances")
val minecraftDirectory: Path = operatingSystem.minecraftDirectory
val javaExecutablePath: Path? = operatingSystem.javaExecutablePath

val HTTP = OkHttpClient.Builder()
Expand All @@ -60,12 +60,13 @@ object Api {

val fabricVersionDownloader = FabricVersionDownloader()
val forgeVersionDownloader = ForgeVersionDownloader()
val neoForgeVersionDownloader = NeoForgeVersionDownloader()
val versionDownloader = VersionDownloader()

init {
instancesDirectory.createDirectories()

val launcherProfiles = path(minecraftDirectory, "launcher_profiles.json")
val launcherProfiles = path(launcherDirectory, "launcher_profiles.json")

if (!launcherProfiles.exists()) {
launcherProfiles.createFile()
Expand Down Expand Up @@ -147,6 +148,7 @@ object Api {
.directory(gameDirectory.toFile())
.inheritIO()
.start()

}

private fun arguments(
Expand Down Expand Up @@ -209,22 +211,10 @@ object Api {
return adapter.arguments
}

enum class OperatingSystem(
val minecraftDirectory: Path,
var javaExecutablePath: Path?
) {
Windows(
path(System.getenv("APPDATA"), ".minecraft"),
path(System.getProperty("java.home"), "bin", "java.exe")
),
Linux(
path(System.getProperty("user.home"), ".minecraft"),
path(System.getProperty("java.home"), "bin", "java")
),
OsX(
path(System.getProperty("user.home"), "Library/Application Support/minecraft/"),
path(System.getProperty("java.home"), "bin", "java")
);
enum class OperatingSystem(var javaExecutablePath: Path?) {
Windows(path(System.getProperty("java.home"), "bin", "java.exe")),
Linux(path(System.getProperty("java.home"), "bin", "java")),
OsX(path(System.getProperty("java.home"), "bin", "java"));

init {
if (!javaExecutablePath!!.exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,23 @@ object JavaVersionManager : JavaVersionContainer {
.command(path.absolutePathString(), "-version")
.start()

return JAVA_VERSION_REGEX
.find(process.errorStream.reader().readText())!!
.groupValues[1]
.let {
when {
it.contains("1.7") -> 7
it.contains("1.8") -> 8
else -> try {
it.split(".")[0].toInt()
} catch (ex: Exception) {
8
return try {
JAVA_VERSION_REGEX
.find(process.errorStream.reader().readText())!!
.groupValues[1]
.let {
when {
it.contains("1.7") -> 7
it.contains("1.8") -> 8
else -> try {
it.split(".")[0].toInt()
} catch (ex: Exception) {
8
}
}
}
}
} finally {
process.destroy()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.kraftia.api.managers

import org.kraftia.api.Api
import org.kraftia.api.extensions.path
import org.kraftia.api.version.Version
import org.kraftia.api.version.container.VersionContainer
import kotlin.io.path.*
Expand All @@ -16,7 +15,7 @@ object VersionManager : VersionContainer {
override fun updateVersions() {
versions.clear()

for (versionDirectory in path(Api.minecraftDirectory, "versions")
for (versionDirectory in Api.versionDownloader.versionsDirectory
.listDirectoryEntries()
.filter { it.isDirectory() }
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.kraftia.api.version

import com.google.gson.*
import com.google.gson.annotations.SerializedName

data class Version(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class FabricVersionDownloader {
id: String,
loaderVersion: String? = null
) {
progress.pushMessage("Downloading $id fabric version")
progress.pushMessage("Downloading $id Fabric version")

val installer = installers.first { it.stable }

Expand All @@ -78,14 +78,14 @@ class FabricVersionDownloader {
}

val process = ProcessBuilder()
.directory(Api.minecraftDirectory.toFile())
.directory(Api.launcherDirectory.toFile())
.command(
JavaVersionManager.current?.executable ?: "java",
"-jar",
installerPath.absolutePathString(),
"client",
"-dir",
Api.minecraftDirectory.absolutePathString(),
Api.launcherDirectory.absolutePathString(),
"-mcversion",
id,
"-loader",
Expand All @@ -96,7 +96,7 @@ class FabricVersionDownloader {
.start()

if (process.waitFor() != 0) {
progress.pushMessage("Failed to install fabric $id")
progress.pushMessage("Failed to install Fabric $id")
}

VersionManager.updateVersions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import kotlin.io.path.absolutePathString
import kotlin.io.path.exists

class ForgeVersionDownloader {
data class Version(val version: String) {
data class AvailableVersion(val version: String) {
val installers by lazy {
FORGE_ENTRY_REGEX
.findAll(get("${FORGE_URL}index_$version.html").body.string().replace("\n", ""))
Expand Down Expand Up @@ -45,11 +45,22 @@ class ForgeVersionDownloader {

private val FORGE_VERSION_PAGE_REGEX =
"<a href=\"index_(.*?).html\">.*?</a>".toRegex()
private val FORGE_VERSION_PAGE_ACTIVE_ELEMENT_REGEX =
"<li class=\"elem-active\">(.*?)</li>".toRegex()

val versions: List<Version> = run {
FORGE_VERSION_PAGE_REGEX.findAll(get(FORGE_URL).body.string()).toList()

val versions: List<AvailableVersion> = run {
val body = get(FORGE_URL).body.string()

listOf(
AvailableVersion(
FORGE_VERSION_PAGE_ACTIVE_ELEMENT_REGEX
.find(body)!!
.groupValues[1]
)
) + FORGE_VERSION_PAGE_REGEX.findAll(body).toList()
.map { matchResult -> matchResult.groupValues[1] }
.map { Version(it) }
.map { AvailableVersion(it) }
}
}

Expand All @@ -58,7 +69,7 @@ class ForgeVersionDownloader {
id: String,
installerId: String? = null
) {
progress.pushMessage("Downloading $id forge version")
progress.pushMessage("Downloading $id Forge version")

val version = versions.first { it.version == id }

Expand Down Expand Up @@ -86,7 +97,7 @@ class ForgeVersionDownloader {
}

val process = ProcessBuilder()
.directory(Api.minecraftDirectory.toFile())
.directory(Api.launcherDirectory.toFile())
.command(
JavaVersionManager.current?.executable ?: "java",
"-jar",
Expand All @@ -98,7 +109,7 @@ class ForgeVersionDownloader {
.start()

if (process.waitFor() != 0) {
progress.pushMessage("Failed to install forge $id")
progress.pushMessage("Failed to install Forge $id")
}

VersionManager.updateVersions()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package org.kraftia.api.version.downloader.downloaders

import com.google.gson.JsonObject
import org.kraftia.api.Api
import org.kraftia.api.extensions.get
import org.kraftia.api.extensions.path
import org.kraftia.api.managers.JavaVersionManager
import org.kraftia.api.managers.VersionManager
import org.kraftia.api.version.downloader.DownloaderProgress
import kotlin.io.path.absolutePathString
import kotlin.io.path.exists

class NeoForgeVersionDownloader {
data class AvailableVersion(
val version: String,
val installers: List<AvailableInstaller>
)

data class AvailableInstaller(
val latest: Boolean,
val id: String,
val downloadUrl: String
)

companion object {
private const val NEOFORGE_MAVEN_URL =
"https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge"

val versions: List<AvailableVersion> = run {
get<JsonObject>(NEOFORGE_MAVEN_URL)
.getAsJsonArray("versions")
.map { it.asString }
.groupBy { it.slice(0..3) }
.map { entry ->
AvailableVersion(
"1.${entry.key}",
entry.value.reversed().mapIndexed { index, it ->
AvailableInstaller(
index == 0,
it,
"https://maven.neoforged.net/releases/net/neoforged/neoforge/$it/neoforge-$it-installer.jar"
)
}
)
}
}
}

fun download(
progress: DownloaderProgress,
id: String,
installerId: String? = null
) {
progress.pushMessage("Downloading $id NeoForge version")

val version = versions.first { it.version == id }

if (version.installers.isEmpty()) {
throw IllegalArgumentException("NeoForge version $id doesn't have installers")
}

val installer = if (installerId != null) {
version.installers.first { it.id == installerId }
} else {
version.installers.first { it.latest }
}

val installerPath = path(
Api.launcherDirectory,
"versions",
"neoforge-${installer.id}",
"installer.jar"
)

if (!installerPath.exists()) {
org.kraftia.api.extensions.download(
url = installer.downloadUrl,
path = installerPath,
progress = progress
)
}

val process = ProcessBuilder()
.directory(Api.launcherDirectory.toFile())
.command(
JavaVersionManager.current?.executable ?: "java",
"-jar",
installerPath.absolutePathString(),
"--installClient"
)
.redirectInput(ProcessBuilder.Redirect.INHERIT)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.start()

if (process.waitFor() != 0) {
progress.pushMessage("Failed to install NeoForge $id")
}

VersionManager.updateVersions()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class VersionDownloader {

data class Result(
val version: org.kraftia.api.version.Version,
val classpath: List<Path>,
val classpath: Set<Path>,
val versionBinDirectory: Path
) {
init {
Expand All @@ -45,10 +45,10 @@ class VersionDownloader {
}
}

val versionsDirectory = path(Api.minecraftDirectory, "versions")
val librariesDirectory = path(Api.minecraftDirectory, "libraries")
val binDirectory = path(Api.launcherDirectory, "bin")
val assetsDirectory = path(Api.minecraftDirectory, "assets")
val versionsDirectory: Path = path(Api.launcherDirectory, "versions").toAbsolutePath()
val librariesDirectory: Path = path(Api.launcherDirectory, "libraries").toAbsolutePath()
val binDirectory: Path = path(Api.launcherDirectory, "bin").toAbsolutePath()
val assetsDirectory: Path = path(Api.launcherDirectory, "assets").toAbsolutePath()

init {
versionsDirectory.createDirectories()
Expand Down Expand Up @@ -82,7 +82,7 @@ class VersionDownloader {
val classpath = download(
progress,
parent
).classpath.toMutableList()
).classpath.toMutableSet()

progress.pushMessage("Downloading ${version.id} version libraries")

Expand Down Expand Up @@ -122,7 +122,7 @@ class VersionDownloader {
throw IllegalArgumentException("Version not found")
}

val classpath = mutableListOf<Path>()
val classpath = mutableSetOf<Path>()

for (library in downloadLibraries(progress, version, versionBinDirectory)) {
classpath.add(library)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fun main() {
CommandManager.addCommand(InstanceCommand)
CommandManager.addCommand(JavaCommand)
CommandManager.addCommand(LaunchCommand)
CommandManager.addCommand(NeoForgeCommand)
CommandManager.addCommand(VersionCommand)

println(resourceText("ascii_logo.txt"))
Expand Down
Loading

0 comments on commit 7ed7d64

Please sign in to comment.