HMCL modpack output model

This commit is contained in:
huangyuhui 2017-08-22 21:07:56 +08:00
parent d83291eac0
commit 86cef86fc9
3 changed files with 179 additions and 4 deletions

View File

@ -22,12 +22,21 @@ import org.jackhuang.hmcl.download.game.VersionJSONSaveTask
import org.jackhuang.hmcl.mod.Modpack import org.jackhuang.hmcl.mod.Modpack
import org.jackhuang.hmcl.setting.Profile import org.jackhuang.hmcl.setting.Profile
import org.jackhuang.hmcl.task.Task import org.jackhuang.hmcl.task.Task
import org.jackhuang.hmcl.util.GSON
import org.jackhuang.hmcl.util.fromJson
import org.jackhuang.hmcl.util.readTextFromZipFile
import org.jackhuang.hmcl.util.unzipSubDirectory
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import sun.misc.IOUtils
import jdk.nashorn.internal.objects.NativeFunction.call
import org.jackhuang.hmcl.task.TaskResult
import org.jackhuang.hmcl.util.*
import sun.plugin2.util.PojoUtil.toJson
import sun.tools.jar.resources.jar
import java.util.Collections.addAll
import java.util.ArrayList
import java.util.Arrays
/** /**
* Read the manifest in a HMCL modpack. * Read the manifest in a HMCL modpack.
@ -71,3 +80,42 @@ class HMCLModpackInstallTask(profile: Profile, private val zipFile: File, privat
json.delete() json.delete()
} }
} }
val MODPACK_BLACK_LIST = listOf("usernamecache.json", "asm", "logs", "backups", "versions", "assets", "usercache.json", "libraries", "crash-reports", "launcher_profiles.json", "NVIDIA", "AMD", "TCNodeTracker", "screenshots", "natives", "native", "\$native", "pack.json", "launcher.jar", "minetweaker.log", "launcher.pack.lzma", "hmclmc.log")
val MODPACK_SUGGESTED_BLACK_LIST = listOf("fonts", "saves", "servers.dat", "options.txt", "optionsof.txt", "journeymap", "optionsshaders.txt", "mods/VoxelMods")
class HMCLModpackExportTask @JvmOverloads constructor(
private val repository: DefaultGameRepository,
private val version: String,
private val blacklist: List<String>,
private val modpack: Modpack,
private val output: File,
override val id: String = ID): TaskResult<ZipEngine>() {
override fun execute() {
val b = ArrayList<String>(MODPACK_BLACK_LIST)
b.addAll(blacklist)
b.add(version + ".jar")
b.add(version + ".json")
LOG.info("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker")
ZipEngine(output).use { zip ->
zip.putDirectory(repository.getRunDirectory(version)) a@ { x: String, y: Boolean ->
for (s in b)
if (y) {
if (x.startsWith(s + "/"))
return@a null
} else if (x == s)
return@a null
"minecraft/" + x
}
val mv = repository.getVersion(version).resolve(repository)
val gameVersion = minecraftVersion(repository.getVersionJar(version)) ?: throw IllegalStateException("Cannot parse the version of $version")
zip.putTextFile(GSON.toJson(mv), "minecraft/pack.json")
zip.putTextFile(GSON.toJson(modpack.copy(gameVersion = gameVersion)), "modpack.json")
}
}
companion object {
val ID = "zip_engine"
}
}

View File

@ -21,6 +21,7 @@ data class Modpack @JvmOverloads constructor(
val name: String = "", val name: String = "",
val author: String = "", val author: String = "",
val version: String = "", val version: String = "",
val gameVersion: String = "",
val description: String = "", val description: String = "",
val manifest: Any? = null val manifest: Any? = null
) )

View File

@ -0,0 +1,126 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see {http://www.gnu.org/licenses/}.
*/
package org.jackhuang.hmcl.util
import java.util.zip.ZipEntry
import java.util.HashSet
import java.io.*
import java.util.zip.ZipOutputStream
/**
* Non thread-safe
*
* @author huangyuhui
*/
class ZipEngine
@Throws(IOException::class)
constructor(f: File) : Closeable {
val buf = ByteArray(1024)
val zos: ZipOutputStream = ZipOutputStream(BufferedOutputStream(f.outputStream()))
private val names = HashSet<String>()
@Throws(IOException::class)
override fun close() {
zos.closeEntry()
zos.close()
}
/**
* 功能 sourceDir 目录下的所有文件进行 zip 格式的压缩保存为指定 zip 文件
*
* @param sourceDir 源文件夹
* @param pathNameCallback callback(pathName, isDirectory) returns your
* modified pathName
*
* @throws java.io.IOException 压缩失败或无法读取
*/
@Throws(IOException::class)
@JvmOverloads
fun putDirectory(sourceDir: File, pathNameCallback: ((String, Boolean) -> String?)? = null) {
putDirectoryImpl(sourceDir, if (sourceDir.isDirectory) sourceDir.path else sourceDir.parent, pathNameCallback)
}
/**
* 将文件压缩成zip文件
*
* @param source zip文件路径
* @param basePath 待压缩文件根目录
* @param zos zip文件的os
* @param pathNameCallback callback(pathName, isDirectory) returns your
* modified pathName, null if you dont want this file zipped
*/
@Throws(IOException::class)
private fun putDirectoryImpl(source: File, basePath: String, pathNameCallback: ((String, Boolean) -> String?)?) {
val files: Array<File>?
if (source.isDirectory)
files = source.listFiles()
else
files = arrayOf(source)
if (files == null)
return
var pathName: String? //存相对路径(相对于待压缩的根目录)
for (file in files)
if (file.isDirectory) {
pathName = file.path.substring(basePath.length + 1) + "/"
pathName = pathName.replace('\\', '/')
if (pathNameCallback != null)
pathName = pathNameCallback(pathName, true)
if (pathName == null)
continue
put(ZipEntry(pathName))
putDirectoryImpl(file, basePath, pathNameCallback)
} else {
if (".DS_Store" == file.name) // For Mac computers.
continue
pathName = file.path.substring(basePath.length + 1)
pathName = pathName.replace('\\', '/')
if (pathNameCallback != null)
pathName = pathNameCallback(pathName, false)
if (pathName == null)
continue
putFile(file, pathName)
}
}
@Throws(IOException::class)
fun putFile(file: File, pathName: String) =
file.inputStream().use { putStream(it, pathName) }
@Throws(IOException::class)
fun putStream(inputStream: InputStream, pathName: String) {
put(ZipEntry(pathName))
inputStream.copyTo(zos, buf)
}
@Throws(IOException::class)
fun putTextFile(text: String, pathName: String) =
putTextFile(text, "UTF-8", pathName)
@Throws(IOException::class)
fun putTextFile(text: String, encoding: String, pathName: String) =
putStream(ByteArrayInputStream(text.toByteArray(charset(encoding))), pathName)
@Throws(IOException::class)
fun put(entry: ZipEntry) {
if (names.add(entry.name))
zos.putNextEntry(entry)
}
}