Skip to content

Commit

Permalink
feat: download and extract default resourcePack for use in other plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy0000 committed Aug 7, 2024
1 parent 29a67ec commit 0fa5659
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package com.mineinabyss.idofront

import com.mineinabyss.idofront.resourcepacks.MinecraftAssetExtractor
import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin

class IdofrontPlugin : JavaPlugin() {

override fun onEnable() {
Bukkit.getAsyncScheduler().runNow(this) {
MinecraftAssetExtractor.extractLatest()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.mineinabyss.idofront.resourcepacks

import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.mineinabyss.idofront.messaging.idofrontLogger
import org.bukkit.Bukkit
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileOutputStream
import java.net.URI
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream


object MinecraftAssetExtractor {

private const val VERSION_MANIFEST_URL = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"
lateinit var assetPath: File

fun extractLatest() {
idofrontLogger.i("Extracting latest vanilla-assets...")
val versionInfo = runCatching {
downloadJson(findVersionInfoUrl() ?: return)?.asJsonObject
}.getOrNull() ?: return

val clientJar = downloadClientJar(versionInfo)
extractJarAssets(clientJar, assetPath)
idofrontLogger.s("Finished extracting vanilla assets for ${assetPath.name}")
}

private fun extractJarAssets(clientJar: ByteArray?, assetPath: File) {
var entry: ZipEntry

ByteArrayInputStream(clientJar).use { inputStream ->
ZipInputStream(inputStream).use { zipInputStream ->

kotlin.runCatching {
while (zipInputStream.nextEntry.also { entry = it } != null) {
if (!entry.name.startsWith("assets/")) continue
if (entry.name.startsWith("assets/minecraft/shaders")) continue
if (entry.name.startsWith("assets/minecraft/particles")) continue

val file = checkAndCreateFile(assetPath, entry)
if (entry.isDirectory && !file.isDirectory && !file.mkdirs())
error("Failed to create directory ${entry.name}")
else {
val parent = file.parentFile
if (!parent.isDirectory && !parent.mkdirs()) error("Failed to create directory ${parent?.path}")

runCatching {
zipInputStream.copyTo(FileOutputStream(file))
}.onFailure {
error("Failed to extract ${entry.name} from ${parent?.path}")
}
}
}
}
}
}
}

private fun checkAndCreateFile(assetPath: File, entry: ZipEntry): File {
val destFile = assetPath.resolve(entry.name)
val dirPath = assetPath.canonicalPath
val filePath = destFile.canonicalPath

if (!filePath.startsWith(dirPath + File.separator)) error("Entry outside target: ${entry.name}")
return destFile
}

private fun downloadClientJar(versionInfo: JsonObject) = runCatching {
val url = versionInfo.getAsJsonObject("downloads").getAsJsonObject("client").get("url").asString
URI(url).toURL().readBytes()
}.onFailure { it.printStackTrace() }.getOrNull() ?: error("Failed to download client JAR")

private fun findVersionInfoUrl(): String? {
val manifest = runCatching {
downloadJson(VERSION_MANIFEST_URL)
}.getOrNull() ?: error("Failed to download version manifest")

val latest = manifest.getAsJsonObject("latest").get("release").asString
assetPath = Bukkit.getPluginsFolder().resolve("Idofront/assetCache/$latest")

if (!assetPath.mkdirs()) {
idofrontLogger.i("Latest has already been extracted for $latest, skipping...")
return null
}

return manifest.getAsJsonArray("versions").firstOrNull {
(it as? JsonObject)?.get("id")?.asString?.equals(latest) ?: false
}?.asJsonObject?.get("url")?.asString ?: error("Failed to find version inof url for version $latest")
}

private fun downloadJson(url: String) = runCatching { JsonParser.parseString(URI.create(url).toURL().readText()) }
.getOrNull()?.takeIf { it.isJsonObject }?.asJsonObject
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ object ResourcePacks {
val resourcePackWriter = MinecraftResourcePackWriter.builder().prettyPrinting(true).build()
val resourcePackReader = MinecraftResourcePackReader.builder().lenient(true).build()

val vanillaDefaultResourcePack by lazy { readToResourcePack(MinecraftAssetExtractor.assetPath) }

fun readToResourcePack(file: File): ResourcePack? {
return runCatching {
when {
Expand Down Expand Up @@ -69,13 +71,13 @@ object ResourcePacks {

if (originalPack.packMeta()?.description().isNullOrEmpty()) mergePack.packMeta()?.let { originalPack.packMeta(it) }
if (originalPack.icon() == null) mergePack.icon()?.let { originalPack.icon(it) }
sortItemOverrides(originalPack)
ensureItemOverridesSorted(originalPack)
}

/**
* Ensures that the ResourcePack's models all have their ItemOverrides sorted based on their CustomModelData
*/
fun sortItemOverrides(resourcePack: ResourcePack) {
fun ensureItemOverridesSorted(resourcePack: ResourcePack) {
resourcePack.models().toHashSet().forEach { model ->
val sortedOverrides = model.overrides().sortedBy { override ->
// value() is a LazilyParsedNumber so convert it to an Int
Expand All @@ -84,4 +86,13 @@ object ResourcePacks {
resourcePack.model(model.toBuilder().overrides(sortedOverrides).build())
}
}

/**
* Ensure that vanilla models, like paper.json etc, have the correct parent-properties
*/
fun ensureVanillaModelProperties(resourcePack: ResourcePack) {
//resourcePack.models().filter { it.key() }.forEach {

//}
}
}

0 comments on commit 0fa5659

Please sign in to comment.