4
0
Fork 0
mirror of https://github.com/Anvilcraft/modpacktools synced 2024-06-11 15:09:24 +02:00
 Conflicts:
	src/main/kotlin/ley/anvil/modpacktools/util/Util.kt
This commit is contained in:
Timo Ley 2020-07-28 16:45:41 +02:00
commit 3a5a26a9b7
12 changed files with 172 additions and 157 deletions

View file

@ -32,20 +32,31 @@ private val httpClient0 = lazy {
.build()
}
val HTTP_CLIENT by httpClient0
private val helpMessage by lazy {
val sb = StringBuilder().append("Commands:\n\n")
LOADER.commands.entries.stream()
//Sort by name
.sorted(Comparator.comparing {e: MutableMap.MutableEntry<String, ICommand> -> e.key})
.forEach {sb.append("${it.key}: ${it.value.helpMessage}\n")}
sb.toString()
}
fun main(args: Array<out String>) {
if(args.isEmpty()) {
printHelp()
println(helpMessage)
} else {
try {
val ret = LOADER.runCommand(args[0], args)
if(ret.hasRet())
println(ret.ret)
} catch(e: NoSuchElementException) {
println(e.message)
printHelp()
println("Command ${args[0]} not found")
println(helpMessage)
} catch(e: CommandLoader.ConfigMissingException) {
println("Config is needed for this command yet it is not present. Run 'init' to generate")
} catch(e: CommandLoader.ModpackJsonMissingException) {
println("Modpackjson is needed for this command yet it is not present.")
}
}
@ -55,11 +66,3 @@ fun main(args: Array<out String>) {
HTTP_CLIENT.connectionPool.evictAll()
}
}
fun printHelp() {
println("Commands:")
LOADER.commands.entries.stream()
//Sort by name
.sorted(Comparator.comparing {e: MutableMap.MutableEntry<String, ICommand> -> e.key})
.forEach {println("${it.key}: ${it.value.helpMessage}")}
}

View file

@ -2,9 +2,10 @@ package ley.anvil.modpacktools.command
import ley.anvil.modpacktools.CONFIG
import ley.anvil.modpacktools.MPJH
import ley.anvil.modpacktools.command.CommandReturn.Companion.fail
import org.reflections.Reflections
import org.reflections.scanners.SubTypesScanner
import kotlin.reflect.KClass
import kotlin.reflect.full.createInstance
/**
* The command loader will scan the given package for {@link ICommand} classes and add them to the command list
@ -12,15 +13,28 @@ import org.reflections.scanners.SubTypesScanner
* @param pkg The package to scan for commands
*/
class CommandLoader(private val pkg: String) {
class ConfigMissingException : IllegalStateException()
class ModpackJsonMissingException : IllegalStateException()
val commands = HashMap<String, ICommand>()
companion object {
/**
* Runs a command statically.
*
* @param args the args to pass to the command
* @throws ConfigMissingException if the command requires a config and it is not found
* @throws ModpackJsonMissingException if the command requires a modpackjson file and it is not found
*/
@JvmStatic
@Throws(ConfigMissingException::class, ModpackJsonMissingException::class)
fun ICommand.runStatic(args: Array<out String>): CommandReturn {
if(this.needsConfig && !CONFIG.configExists())
return fail("Config is needed for this command yet it is not present. Run 'init' to generate")
if(this.needsConfig && !CONFIG.exists)
throw ConfigMissingException()
if(this.needsModpackjson && MPJH.asWrapper == null)
return fail("Modpackjson is needed for this command yet it is not present.")
throw ModpackJsonMissingException()
return this.execute(args)
}
}
@ -35,11 +49,14 @@ class CommandLoader(private val pkg: String) {
val refs = Reflections(pkg, SubTypesScanner(false))
refs.getSubTypesOf(ICommand::class.java).stream()
.map {it.kotlin}
//Only annotated classes
.filter {it.isAnnotationPresent(LoadCommand::class.java)}
//Cannot use it.hasAnnotation because it is experimental and requires everything to be annotated so this makes more sense
.filter {it.annotations.any {ann -> ann.annotationClass == LoadCommand::class}}
//can be object
.map {it.kotlin.objectInstance ?: it}
.forEach {if(it is ICommand) addCommand(it) else addClass(it as Class<out ICommand>)}
.map {it.objectInstance ?: it}
//create new instance if it is a class, otherwise just add the current instance
.forEach {if(it is ICommand) addCommand(it) else addClass(it as KClass<out ICommand>)}
}
/**
@ -48,7 +65,7 @@ class CommandLoader(private val pkg: String) {
* @param clazz the class to add
* @return if it was successful
*/
fun addClass(clazz: Class<out ICommand>) = addCommand(clazz.newInstance())
fun addClass(clazz: KClass<out ICommand>) = addCommand(clazz.createInstance())
/**
* Adds a command to the command list with the name that getName() returns

View file

@ -1,6 +1,7 @@
package ley.anvil.modpacktools.commands
import j2html.TagCreator.*
import j2html.utils.CSSMin.compressCss
import ley.anvil.addonscript.wrapper.ASWrapper
import ley.anvil.addonscript.wrapper.ArtifactDestination
import ley.anvil.addonscript.wrapper.MetaData
@ -12,8 +13,10 @@ import ley.anvil.modpacktools.command.ICommand
import ley.anvil.modpacktools.command.LoadCommand
import org.apache.commons.csv.CSVFormat
import org.apache.commons.csv.CSVPrinter
import org.apache.commons.io.IOUtils
import java.io.File
import java.io.FileWriter
import java.nio.charset.StandardCharsets
@LoadCommand
object CreateModlist : ICommand {
@ -61,30 +64,7 @@ object CreateModlist : ICommand {
head(
style(
//Fancy css!
"""
a:link {
color: #ff5555;
}
a:visited {
color: #cc55cc;
}
body {
background-color: #333333;
color: #ffffff
}
.img {
width:100px;
}
td {
border: #999999 3px;
border-style: solid;
}
.description {
width: 100%
}
"""
//trim unnecessary chars
.trimIndent().filter {it != '\n'}
compressCss(IOUtils.toString(ClassLoader.getSystemResourceAsStream("commands/createmodlist/style.css"), StandardCharsets.UTF_8))
)
),
body(
@ -97,10 +77,10 @@ td {
),
each(getMods()) {
tr(
td(a(
td(if(it.icon != null) a(
img().withSrc(it.icon)
.withClass("img")
).withHref(it.website)
).withHref(it.website) else null
),
td(a(it.name)
.withHref(it.website)
@ -112,7 +92,9 @@ td {
li(contr.key)
}
)),
td(it.description?.joinToString("<br />") ?: "")
td(each(it.description?.asList() ?: listOf()) {d: String ->
p(d)
})
.withClass("description")
)
}

View file

@ -15,7 +15,7 @@ object Init : ICommand {
override val needsModpackjson: Boolean = false
override fun execute(args: Array<out String>): CommandReturn {
if(CONFIG.configExists())
if(CONFIG.exists)
return fail("Config exists")
CONFIG.copyConfig()
return success("Config Created")

View file

@ -1,76 +0,0 @@
package ley.anvil.modpacktools.util
import ley.anvil.addonscript.curse.ManifestJSON
import ley.anvil.addonscript.wrapper.ASWrapper
fun convertAStoManifest(addonscript: ASWrapper): ManifestLinksPair {
var ml = ManifestLinksPair()
var ver = addonscript.defaultVersion
var manifest = ManifestJSON()
var mcv = ver.version?.mcversion!![0]
manifest.minecraft = ManifestJSON.Minecraft()
manifest.minecraft.version = mcv
manifest.minecraft.modLoaders = mutableListOf()
manifest.files = mutableListOf()
manifest.manifestType = "minecraftModpack"
manifest.manifestVersion = 1
manifest.name = addonscript.json.meta!!.name
if (manifest.name == null)
manifest.name = addonscript.json.id
manifest.version = ver.versionName
manifest.author = addonscript.json!!.meta!!.contributors[0].name
for (rel in ver.getRelations(arrayOf("client"), null)) {
if (rel.isModloader) {
if (rel.relation.id == "forge") {
var forge = ManifestJSON.Modloader()
forge.primary = true
forge.id = "forge-" + rel.versions.latestKnown
manifest.minecraft.modLoaders.add(forge)
} else {
println("Curse only allows Forge as a modloader. " + rel.relation.id + " is not allowed!")
}
} else if (rel.hasFile()) {
var file = rel.file
if (file.file.installer == "internal.jar") {
println("internal.jar is not supportet on Curse")
continue
} else if (file.isArtifact) {
var art = file.artifact
if (art.isCurseforge) {
var f = ManifestJSON.File()
f.fileID = art.fileID
f.projectID = art.projectID
f.required = rel.options.contains("required")
manifest.files.add(f);
}
} else if (rel.options.contains("required")) {
ml.links.put(file.get(), file.file.installer)
}
}
}
for (file in ver.getFiles(arrayOf("client", "required"), null)) {
if (file.file.installer == "internal.jar") {
println("internal.jar is not supportet on Curse")
continue
} else if (file.isArtifact) {
var art = file.artifact
if (art.isCurseforge) {
var f = ManifestJSON.File()
f.fileID = art.fileID
f.projectID = art.projectID
f.required = true
manifest.files.add(f);
}
} else {
ml.links.put(file.get(), file.file.installer)
}
}
ml.manifest = manifest
return ml
}

View file

@ -4,21 +4,7 @@ import org.apache.commons.io.FileUtils
import java.io.File
class Config(val configName: String) {
val jarLocation by lazy {
//Get the Location of the jarfile
var file = File(
this::class.java
.protectionDomain
.codeSource
.location
.toURI()
)
//Ensure That JAR_LOCATION is the jarfile's directory and not the file itself
if(file.isFile)
file = file.parentFile
file
}
val configLocation by lazy {File(jarLocation, configName)}
val configLocation by lazy {File(configName)}
val config by lazy {readConfig()}
/**
@ -27,7 +13,7 @@ class Config(val configName: String) {
* @return the Toml object of the config file
*/
private fun readConfig(): CustomToml {
return if(configExists()) {
return if(exists) {
//parse file to toml
CustomToml().read(configLocation) as CustomToml
//reads config from resources if no config file exists as a default value. commands that require the config still won't run without it
@ -39,7 +25,7 @@ class Config(val configName: String) {
*
* @return true if the config file exists
*/
fun configExists(): Boolean = configLocation.exists()
val exists: Boolean = configLocation.exists()
/**
* Copies the Config file from the resources into the tool's folder

View file

@ -1,17 +1,14 @@
package ley.anvil.modpacktools.util
import com.moandjiezana.toml.Toml
import kotlin.reflect.full.functions
import kotlin.reflect.jvm.isAccessible
class CustomToml : Toml() {
companion object {
@JvmStatic
fun Toml.get(key: String): Any? {
//Getting Around things being private for no reason 101 (dont look :P)
val getFunc = this::class.functions.reduce {a, b -> if(b.name == "get") b else a}
getFunc.isAccessible = true
return getFunc.call(this, key)
val getFunc by lazy {Toml::class.getFun("get")}
return getFunc?.call(this, key)
}
}

View file

@ -1,11 +0,0 @@
package ley.anvil.modpacktools.util
import ley.anvil.addonscript.curse.ManifestJSON
import ley.anvil.addonscript.wrapper.FileOrLink
class ManifestLinksPair {
var manifest: ManifestJSON? = null
var links: MutableMap<FileOrLink, String> = HashMap()
}

View file

@ -15,6 +15,10 @@ import java.net.URL
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.full.functions
import kotlin.reflect.jvm.isAccessible
/**
* Reads a Json File
@ -90,6 +94,14 @@ fun URL.sanitize(): URL? {
}
}
/**
* gets a function from the receiver and makes it accessible
*
* @param name the name of the function to get
* @receiver the class to get the function from
*/
fun KClass<*>.getFun(name: String): KFunction<*>? = this.functions.find {it.name == name}?.apply {isAccessible = true}
fun zipDir(dir: File, parent: String?, zip: ZipOutputStream) {
for (file in dir.listFiles()){
println(file.name)

View file

@ -0,0 +1,75 @@
package ley.anvil.modpacktools.util.manifest
import ley.anvil.addonscript.curse.ManifestJSON
import ley.anvil.addonscript.wrapper.ASWrapper
fun convertAStoManifest(addonscript: ASWrapper): ManifestLinksPair {
val ml = ManifestLinksPair()
val ver = addonscript.defaultVersion
val manifest = ManifestJSON()
val mcv = ver.version!!.mcversion[0]
manifest.minecraft = ManifestJSON.Minecraft()
manifest.minecraft.version = mcv
manifest.minecraft.modLoaders = mutableListOf()
manifest.files = mutableListOf()
manifest.manifestType = "minecraftModpack"
manifest.manifestVersion = 1
manifest.name = addonscript.json.meta!!.name ?: addonscript.json.id
manifest.version = ver.versionName
manifest.author = addonscript.json!!.meta!!.contributors[0].name
for(rel in ver.getRelations(arrayOf("client"), null)) {
if(rel.isModloader) {
if(rel.relation.id == "forge") {
val forge = ManifestJSON.Modloader()
forge.primary = true
forge.id = "forge-" + rel.versions.latestKnown
manifest.minecraft.modLoaders.add(forge)
} else {
println("Curse only allows Forge as a modloader. ${rel.relation.id} is not allowed!")
}
} else if(rel.hasFile()) {
val file = rel.file
//TODO deduplicate this
if(file.file.installer == "internal.jar") {
println("internal.jar is not supported on Curse")
continue
} else if(file.isArtifact) {
val art = file.artifact
if(art.isCurseforge) {
val f = ManifestJSON.File()
f.fileID = art.fileID
f.projectID = art.projectID
f.required = rel.options.contains("required")
manifest.files.add(f)
}
} else if(rel.options.contains("required")) {
ml.links[file.get()] = file.file.installer
}
}
}
for(file in ver.getFiles(arrayOf("client", "required"), null)) {
if(file.file.installer == "internal.jar") {
println("internal.jar is not supported on Curse")
continue
} else if(file.isArtifact) {
val art = file.artifact
if(art.isCurseforge) {
val f = ManifestJSON.File()
f.fileID = art.fileID
f.projectID = art.projectID
f.required = true
manifest.files.add(f)
}
} else {
ml.links[file.get()] = file.file.installer
}
}
ml.manifest = manifest
return ml
}

View file

@ -0,0 +1,9 @@
package ley.anvil.modpacktools.util.manifest
import ley.anvil.addonscript.curse.ManifestJSON
import ley.anvil.addonscript.wrapper.FileOrLink
data class ManifestLinksPair (
var manifest: ManifestJSON? = null,
var links: MutableMap<FileOrLink, String> = mutableMapOf()
)

View file

@ -0,0 +1,21 @@
a:link {
color: #ff5555;
}
a:visited {
color: #cc55cc;
}
body {
background-color: #333333;
color: #ffffff;
font-family: sans-serif;
}
.img {
width: 100px;
}
td {
border: #999999 3px;
border-style: solid;
}
.description {
width: 100%;
}