mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-11 22:31:52 +09:00
205 lines
7.1 KiB
Kotlin
205 lines
7.1 KiB
Kotlin
package net.torvald.terrarum
|
|
|
|
import com.badlogic.gdx.Gdx
|
|
import com.badlogic.gdx.files.FileHandle
|
|
import net.torvald.terrarum.utils.CSVFetcher
|
|
import net.torvald.terrarum.itemproperties.GameItem
|
|
import net.torvald.terrarum.itemproperties.ItemCodex
|
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
|
import net.torvald.terrarum.itemproperties.ItemID
|
|
import net.torvald.terrarum.langpack.Lang
|
|
import net.torvald.terrarum.utils.JsonFetcher
|
|
import org.apache.commons.csv.CSVFormat
|
|
import org.apache.commons.csv.CSVParser
|
|
import java.io.File
|
|
import java.io.FileInputStream
|
|
import java.io.FileNotFoundException
|
|
import java.io.FileReader
|
|
import java.nio.file.FileSystems
|
|
import java.util.*
|
|
import javax.script.ScriptEngineManager
|
|
import javax.script.Invocable
|
|
|
|
|
|
|
|
/**
|
|
* Modules Resource Manager
|
|
*
|
|
*
|
|
* NOTE!!: Usage of Groovy is only temporary; if Kotlin's "JSR 223" is no longer experimental and
|
|
* is readily available, ditch that Groovy.
|
|
*
|
|
*
|
|
* Created by minjaesong on 2017-04-17.
|
|
*/
|
|
object ModMgr {
|
|
|
|
val groovyEngine = ScriptEngineManager().getEngineByExtension("groovy")!!
|
|
val groovyInvocable = groovyEngine as Invocable
|
|
|
|
val metaFilename = "metadata.properties"
|
|
val defaultConfigFilename = "default.json"
|
|
|
|
data class ModuleMetadata(
|
|
val order: Int,
|
|
val isDir: Boolean,
|
|
val properName: String,
|
|
val description: String,
|
|
val author: String,
|
|
val entryPoint: String,
|
|
val releaseDate: String,
|
|
val version: String,
|
|
val libraries: Array<String>
|
|
) {
|
|
override fun toString() =
|
|
"\tModule #$order -- $properName | $version | $author\n" +
|
|
"\t$description | $releaseDate\n" +
|
|
"\tEntry point: $entryPoint\n" +
|
|
"\tExternal libraries: ${libraries.joinToString(", ")}"
|
|
}
|
|
const val modDir = "./assets/modules"
|
|
|
|
val moduleInfo = HashMap<String, ModuleMetadata>()
|
|
|
|
init {
|
|
// load modules
|
|
val loadOrderCSVparser = CSVParser.parse(
|
|
FileSystems.getDefault().getPath("$modDir/LoadOrder.csv").toFile(),
|
|
Charsets.UTF_8,
|
|
CSVFormat.DEFAULT.withCommentMarker('#')
|
|
)
|
|
val loadOrder = loadOrderCSVparser.records
|
|
loadOrderCSVparser.close()
|
|
|
|
|
|
loadOrder.forEachIndexed { index, it ->
|
|
val moduleName = it[0]
|
|
println("[ModMgr] Loading module $moduleName")
|
|
|
|
try {
|
|
val modMetadata = Properties()
|
|
modMetadata.load(FileInputStream("$modDir/$moduleName/$metaFilename"))
|
|
|
|
if (File("$modDir/$moduleName/$defaultConfigFilename").exists()) {
|
|
val defaultConfig = JsonFetcher("$modDir/$moduleName/$defaultConfigFilename")
|
|
// read config and store it to the game
|
|
|
|
// write to user's config file
|
|
}
|
|
|
|
|
|
|
|
val properName = modMetadata.getProperty("propername")
|
|
val description = modMetadata.getProperty("description")
|
|
val author = modMetadata.getProperty("author")
|
|
val entryPoint = modMetadata.getProperty("entrypoint")
|
|
val releaseDate = modMetadata.getProperty("releasedate")
|
|
val version = modMetadata.getProperty("version")
|
|
val libs = modMetadata.getProperty("libraries").split(';').toTypedArray()
|
|
val isDir = FileSystems.getDefault().getPath("$modDir/$moduleName").toFile().isDirectory
|
|
moduleInfo[moduleName] = ModuleMetadata(index, isDir, properName, description, author, entryPoint, releaseDate, version, libs)
|
|
|
|
println(moduleInfo[moduleName])
|
|
|
|
|
|
// run entry script in entry point
|
|
if (entryPoint.isNotBlank()) {
|
|
val extension = entryPoint.split('.').last()
|
|
val engine = ScriptEngineManager().getEngineByExtension(extension)!!
|
|
val invocable = engine as Invocable
|
|
engine.eval(FileReader(getFile(moduleName, entryPoint)))
|
|
invocable.invokeFunction("invoke", moduleName)
|
|
}
|
|
|
|
|
|
println("[ModMgr] $moduleName loaded successfully")
|
|
}
|
|
catch (noSuchModule: FileNotFoundException) {
|
|
System.err.println("[ModMgr] No such module: $moduleName, skipping...")
|
|
}
|
|
}
|
|
|
|
|
|
// lists available engines
|
|
/*val manager = ScriptEngineManager()
|
|
val factories = manager.engineFactories
|
|
for (f in factories) {
|
|
println("engine name:" + f.engineName)
|
|
println("engine version:" + f.engineVersion)
|
|
println("language name:" + f.languageName)
|
|
println("language version:" + f.languageVersion)
|
|
println("names:" + f.names)
|
|
println("mime:" + f.mimeTypes)
|
|
println("extension:" + f.extensions)
|
|
println("-----------------------------------------------")
|
|
}*/
|
|
}
|
|
|
|
private fun checkExistence(module: String) {
|
|
if (!moduleInfo.containsKey(module))
|
|
throw FileNotFoundException("No such module: $module")
|
|
}
|
|
private fun String.sanitisePath() = if (this[0] == '/' || this[0] == '\\')
|
|
this.substring(1..this.lastIndex)
|
|
else this
|
|
|
|
|
|
|
|
fun getPath(module: String, path: String): String {
|
|
checkExistence(module)
|
|
return "$modDir/$module/${path.sanitisePath()}"
|
|
}
|
|
fun getGdxFile(module: String, path: String): FileHandle {
|
|
return Gdx.files.internal(getPath(module, path))
|
|
}
|
|
fun getFile(module: String, path: String): File {
|
|
checkExistence(module)
|
|
return FileSystems.getDefault().getPath(getPath(module, path)).toFile()
|
|
}
|
|
fun getFiles(module: String, path: String): Array<File> {
|
|
checkExistence(module)
|
|
val dir = FileSystems.getDefault().getPath(getPath(module, path)).toFile()
|
|
if (!dir.isDirectory) {
|
|
throw FileNotFoundException("The path is not a directory")
|
|
}
|
|
else {
|
|
return dir.listFiles()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
object GameBlockLoader {
|
|
val blockPath = "blocks/"
|
|
|
|
@JvmStatic operator fun invoke(module: String) {
|
|
BlockCodex(module, blockPath + "blocks.csv")
|
|
}
|
|
}
|
|
|
|
object GameItemLoader {
|
|
val itemPath = "items/"
|
|
|
|
@JvmStatic operator fun invoke(module: String) {
|
|
val csv = CSVFetcher.readFromModule(module, itemPath + "itemid.csv")
|
|
csv.forEach {
|
|
val className = it["classname"].toString()
|
|
val itemID = it["id"].toInt()
|
|
|
|
val loadedClass = Class.forName(className)
|
|
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
|
|
val loadedClassInstance = loadedClassConstructor.newInstance(itemID)
|
|
|
|
ItemCodex[itemID] = loadedClassInstance as GameItem
|
|
}
|
|
}
|
|
}
|
|
|
|
object GameLanguageLoader {
|
|
val langPath = "locales/"
|
|
|
|
@JvmStatic operator fun invoke(module: String) {
|
|
Lang.load(getPath(module, langPath))
|
|
}
|
|
}
|
|
} |