diff --git a/build.gradle.kts b/build.gradle.kts
index 8a8676427..4477914ef 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -307,6 +307,7 @@ dependencies {
implementation("org.kamranzafar", "jtar", "2.3")
implementation("org.reflections", "reflections", "0.10.2")
implementation("it.unimi.dsi", "fastutil-core", "8.5.9")
+ implementation("org.xeustechnologies", "jcl-core", version = "2.8")
// ikonli
diff --git a/doc/Modding2.md b/doc/Modding2.md
index c2f6ab35f..178e87e41 100644
--- a/doc/Modding2.md
+++ b/doc/Modding2.md
@@ -22,7 +22,6 @@
- load meta -> inject to classpath -> initialize main class
- main class template (with logging, assets, ...)
- Multiple `mods` folders
- - pre load (before loading anything)
- - while load (while loading everything else)
- - background load (start loading in while, but don't wait for them. Only wait before loading connection)
- - connection load (load before connecting to server)
+ - pre boot (before loading anything)
+ - boot (while loading everything else)
+ - post boot (start loading in while, but don't wait for them. Only wait before loading connection)
diff --git a/src/main/java/de/bixilon/minosoft/Minosoft.kt b/src/main/java/de/bixilon/minosoft/Minosoft.kt
index cf2727533..68e03a279 100644
--- a/src/main/java/de/bixilon/minosoft/Minosoft.kt
+++ b/src/main/java/de/bixilon/minosoft/Minosoft.kt
@@ -42,6 +42,8 @@ import de.bixilon.minosoft.gui.eros.util.JavaFXInitializer
import de.bixilon.minosoft.main.BootTasks
import de.bixilon.minosoft.modding.event.events.FinishInitializingEvent
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
+import de.bixilon.minosoft.modding.loader.LoadingPhases
+import de.bixilon.minosoft.modding.loader.ModLoader
import de.bixilon.minosoft.properties.MinosoftPropertiesLoader
import de.bixilon.minosoft.protocol.packets.factory.PacketTypeRegistry
import de.bixilon.minosoft.protocol.protocol.LANServerListener
@@ -70,11 +72,15 @@ object Minosoft {
val start = nanos()
Log::class.java.forceInit()
CommandLineArguments.parse(args)
+ Log.log(LogMessageType.OTHER, LogLevels.INFO) { "Starting minosoft..." }
+
KUtil.initUtilClasses()
KUtil.init()
+ ModLoader.initModLoading()
+ ModLoader.load(LoadingPhases.PRE_BOOT, CountUpAndDownLatch(0))
+ ModLoader.await(LoadingPhases.PRE_BOOT)
MINOSOFT_ASSETS_MANAGER.load(CountUpAndDownLatch(0))
- Log.log(LogMessageType.OTHER, LogLevels.INFO) { "Starting minosoft..." }
warnMacOS()
MinosoftPropertiesLoader.load()
@@ -105,6 +111,7 @@ object Minosoft {
taskWorker += WorkerTask(identifier = BootTasks.YGGDRASIL, executor = { YggdrasilUtil.load() })
taskWorker += WorkerTask(identifier = BootTasks.ASSETS_OVERRIDE, executor = { OVERRIDE_ASSETS_MANAGER.load(it) })
+ taskWorker += WorkerTask(identifier = BootTasks.MODS, executor = { ModLoader.load(LoadingPhases.BOOT, it) })
taskWorker.work(BOOT_LATCH)
@@ -114,6 +121,7 @@ object Minosoft {
val end = nanos()
Log.log(LogMessageType.OTHER, LogLevels.INFO) { "Minosoft boot sequence finished in ${(end - start).formatNanos()}!" }
GlobalEventMaster.fireEvent(FinishInitializingEvent())
+ DefaultThreadPool += { ModLoader.load(LoadingPhases.POST_BOOT, CountUpAndDownLatch(0)) }
RunConfiguration.AUTO_CONNECT_TO?.let { AutoConnect.autoConnect(it) }
diff --git a/src/main/java/de/bixilon/minosoft/main/BootTasks.kt b/src/main/java/de/bixilon/minosoft/main/BootTasks.kt
index e1c86c5e1..65bbba6f1 100644
--- a/src/main/java/de/bixilon/minosoft/main/BootTasks.kt
+++ b/src/main/java/de/bixilon/minosoft/main/BootTasks.kt
@@ -27,5 +27,6 @@ enum class BootTasks {
STARTUP_PROGRESS,
ASSETS_OVERRIDE,
CLI,
+ MODS,
;
}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/LoaderUtil.kt b/src/main/java/de/bixilon/minosoft/modding/loader/LoaderUtil.kt
new file mode 100644
index 000000000..968144f5a
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/LoaderUtil.kt
@@ -0,0 +1,50 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader
+
+import de.bixilon.kutil.cast.CastUtil.unsafeCast
+import org.xeustechnologies.jcl.JarClassLoader
+import org.xeustechnologies.jcl.JarResources
+import org.xeustechnologies.jcl.JclJarEntry
+import java.util.jar.JarEntry
+import java.util.jar.JarInputStream
+
+object LoaderUtil {
+ private val contentsField = JarResources::class.java.getDeclaredField("jarEntryContents")
+ private val classpathResourcesField = JarClassLoader::class.java.getDeclaredField("classpathResources")
+
+ init {
+ contentsField.isAccessible = true
+ classpathResourcesField.isAccessible = true
+ }
+
+ val JarResources.contents: MutableMap
+ get() = contentsField.get(this).unsafeCast()
+
+
+ val JarClassLoader.classpathResources: JarResources
+ get() = classpathResourcesField.get(this).unsafeCast()
+
+ fun JarClassLoader.load(entry: JarEntry, stream: JarInputStream) {
+ load(entry.name, stream.readAllBytes())
+ }
+
+ fun JarClassLoader.load(name: String, data: ByteArray) {
+ val content = this.classpathResources.contents
+ val entry = JclJarEntry()
+ entry.baseUrl = null
+ entry.resourceBytes = data
+ content[name] = entry
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/LoadingPhases.kt b/src/main/java/de/bixilon/minosoft/modding/loader/LoadingPhases.kt
new file mode 100644
index 000000000..7f2a70405
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/LoadingPhases.kt
@@ -0,0 +1,29 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader
+
+import de.bixilon.kutil.enums.EnumUtil
+import de.bixilon.kutil.enums.ValuesEnum
+
+enum class LoadingPhases {
+ PRE_BOOT,
+ BOOT,
+ POST_BOOT,
+ ;
+
+ companion object : ValuesEnum {
+ override val VALUES: Array = values()
+ override val NAME_MAP: Map = EnumUtil.getEnumValues(VALUES)
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt b/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt
new file mode 100644
index 000000000..7c80133b4
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt
@@ -0,0 +1,208 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader
+
+import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
+import de.bixilon.kutil.concurrent.worker.unconditional.UnconditionalWorker
+import de.bixilon.kutil.latch.CountUpAndDownLatch
+import de.bixilon.kutil.watcher.DataWatcher.Companion.watched
+import de.bixilon.minosoft.assets.util.FileUtil.readJson
+import de.bixilon.minosoft.modding.loader.LoaderUtil.load
+import de.bixilon.minosoft.modding.loader.mod.MinosoftMod
+import de.bixilon.minosoft.modding.loader.mod.ModMain
+import de.bixilon.minosoft.terminal.RunConfiguration
+import de.bixilon.minosoft.util.logging.Log
+import de.bixilon.minosoft.util.logging.LogLevels
+import de.bixilon.minosoft.util.logging.LogMessageType
+import java.io.File
+import java.io.FileInputStream
+import java.util.jar.JarEntry
+import java.util.jar.JarInputStream
+
+
+object ModLoader {
+ private val BASE_PATH = RunConfiguration.HOME_DIRECTORY + "mods/"
+ private const val MANFIEST = "manifest.json"
+ private val mods: MutableList = mutableListOf()
+ private var latch: CountUpAndDownLatch? = null
+ var currentPhase by watched(LoadingPhases.PRE_BOOT)
+ private set
+ var state by watched(PhaseStates.WAITING)
+ private set
+
+ private val LoadingPhases.path: File get() = File(BASE_PATH + name.lowercase())
+
+ private fun createDirectories() {
+ val created: MutableList = mutableListOf()
+ for (phase in LoadingPhases.VALUES) {
+ val path = phase.path
+ if (!path.exists()) {
+ path.mkdirs()
+ created += phase
+ }
+ }
+ if (created.isNotEmpty()) {
+ Log.log(LogMessageType.MOD_LOADING, LogLevels.VERBOSE) { "Created mod folders: $created" }
+ }
+ }
+
+ fun initModLoading() {
+ DefaultThreadPool += { createDirectories() }
+ }
+
+ private fun MinosoftMod.processFile(path: String, data: ByteArray) {
+ TODO("Directory")
+ }
+
+ private fun MinosoftMod.processJar(file: File) {
+ val stream = JarInputStream(FileInputStream(file))
+ while (true) {
+ val entry = stream.nextEntry ?: break
+ if (entry.isDirectory) {
+ continue
+ }
+
+ if (entry.name.endsWith(".class") && entry is JarEntry) {
+ this.classLoader.load(entry, stream)
+ } else if (entry.name.startsWith("assets/")) {
+ TODO("Assets")
+ } else if (entry.name == MANFIEST) {
+ manifest = stream.readJson(false)
+ }
+ }
+ stream.close()
+ }
+
+ private fun MinosoftMod.construct() {
+ val manifest = manifest ?: throw IllegalStateException("Mod $path has no manifest!")
+ val mainClass = Class.forName(manifest.main, true, classLoader)
+ val main = mainClass.kotlin.objectInstance ?: throw IllegalStateException("${manifest.main} is not an kotlin object!")
+ if (main !is ModMain) {
+ throw IllegalStateException("${manifest.main} does not inherit ModMain!")
+ }
+ this.main = main
+ main.init()
+ }
+
+ private fun MinosoftMod.postInit() {
+ main!!.postInit()
+ }
+
+ @Synchronized
+ fun load(phase: LoadingPhases, latch: CountUpAndDownLatch) {
+ if (RunConfiguration.IGNORE_MODS) {
+ return
+ }
+ Log.log(LogMessageType.MOD_LOADING, LogLevels.VERBOSE) { "Starting mod load: $phase" }
+ // ToDo: check phase
+ this.currentPhase = phase
+
+ val inner = CountUpAndDownLatch(1, latch)
+ this.latch = inner
+ this.state = PhaseStates.LISTING
+
+ val path = phase.path
+ val files = path.listFiles()
+ if (files == null || files.isEmpty()) {
+ // no mods to load
+ inner.dec()
+ state = PhaseStates.COMPLETE
+ return
+ }
+ val mods: MutableList = mutableListOf()
+
+ state = PhaseStates.INJECTING
+ for (file in files) {
+ if (!file.isDirectory && !file.name.endsWith(".jar") && !file.name.endsWith(".zip")) {
+ continue
+ }
+ val mod = MinosoftMod(file, phase, CountUpAndDownLatch(3, inner))
+ Log.log(LogMessageType.MOD_LOADING, LogLevels.VERBOSE) { "Injecting $file" }
+ try {
+ if (file.isDirectory) {
+ TODO("Scanning directory")
+ }
+ mod.processJar(file)
+ mods += mod
+ mod.latch.dec()
+ } catch (exception: Throwable) {
+ Log.log(LogMessageType.MOD_LOADING, LogLevels.WARN) { "Error injecting mod: $file" }
+ exception.printStackTrace()
+ mod.latch.count = 0
+ }
+ }
+
+
+ state = PhaseStates.CONSTRUCTING
+ var worker = UnconditionalWorker()
+ for (mod in mods) {
+ worker += {
+ try {
+ mod.construct()
+ mod.latch.dec()
+ } catch (error: Throwable) {
+ mod.latch.count = 0
+ error.printStackTrace()
+ mods -= mod
+ }
+ }
+ }
+ worker.work(inner)
+
+ state = PhaseStates.POST_INIT
+ worker = UnconditionalWorker()
+ for (mod in mods) {
+ worker += {
+ try {
+ mod.postInit()
+ mod.latch.dec()
+ } catch (error: Throwable) {
+ mod.latch.count = 0
+ error.printStackTrace()
+ mods -= mod
+ }
+ }
+ }
+ worker.work(inner)
+
+
+ this.mods += mods
+ state = PhaseStates.COMPLETE
+ inner.dec()
+ if (phase == LoadingPhases.POST_BOOT) {
+ Log.log(LogMessageType.MOD_LOADING, LogLevels.INFO) { "Mod loading completed!" }
+ }
+ }
+
+ fun await(phase: LoadingPhases) {
+ if (RunConfiguration.IGNORE_MODS) {
+ return
+ }
+ val latch = this.latch
+ val currentPhase = this.currentPhase
+ val state = this.state
+ if (currentPhase == phase) {
+ if (state == PhaseStates.COMPLETE) {
+ return
+ }
+ latch!!.await() // ToDo: What if phase has not started yet?
+ return
+ }
+ if (phase.ordinal < currentPhase.ordinal) {
+ // already done
+ return
+ }
+ throw IllegalStateException("$phase has not started yet!")
+ }
+}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/PhaseStates.kt b/src/main/java/de/bixilon/minosoft/modding/loader/PhaseStates.kt
new file mode 100644
index 000000000..f7106956a
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/PhaseStates.kt
@@ -0,0 +1,24 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader
+
+enum class PhaseStates {
+ WAITING,
+ LISTING,
+ INJECTING,
+ CONSTRUCTING,
+ POST_INIT,
+ COMPLETE,
+ ;
+}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/mod/MinosoftMod.kt b/src/main/java/de/bixilon/minosoft/modding/loader/mod/MinosoftMod.kt
new file mode 100644
index 000000000..d3d3eec85
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/mod/MinosoftMod.kt
@@ -0,0 +1,32 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader.mod
+
+import de.bixilon.kutil.latch.CountUpAndDownLatch
+import de.bixilon.minosoft.assets.AssetsManager
+import de.bixilon.minosoft.modding.loader.LoadingPhases
+import de.bixilon.minosoft.modding.loader.mod.manifest.ModManifest
+import org.xeustechnologies.jcl.JarClassLoader
+import java.io.File
+
+class MinosoftMod(
+ val path: File,
+ val phase: LoadingPhases,
+ val latch: CountUpAndDownLatch,
+) {
+ val classLoader = JarClassLoader()
+ var manifest: ModManifest? = null
+ var assetsManager: AssetsManager? = null
+ var main: ModMain? = null
+}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/mod/ModMain.kt b/src/main/java/de/bixilon/minosoft/modding/loader/mod/ModMain.kt
new file mode 100644
index 000000000..16b75fbe2
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/mod/ModMain.kt
@@ -0,0 +1,22 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader.mod
+
+import de.bixilon.kutil.cast.CastUtil.unsafeNull
+import de.bixilon.minosoft.assets.AssetsManager
+import de.bixilon.minosoft.gui.rendering.gui.hud.Initializable
+
+abstract class ModMain : Initializable {
+ val assets: AssetsManager = unsafeNull()
+}
diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/mod/manifest/ModManifest.kt b/src/main/java/de/bixilon/minosoft/modding/loader/mod/manifest/ModManifest.kt
new file mode 100644
index 000000000..4f4b95f6a
--- /dev/null
+++ b/src/main/java/de/bixilon/minosoft/modding/loader/mod/manifest/ModManifest.kt
@@ -0,0 +1,23 @@
+/*
+ * Minosoft
+ * Copyright (C) 2020-2022 Moritz Zwerger
+ *
+ * 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 .
+ *
+ * This software is not affiliated with Mojang AB, the original developer of Minecraft.
+ */
+
+package de.bixilon.minosoft.modding.loader.mod.manifest
+
+import java.util.*
+
+data class ModManifest(
+ val name: String,
+ val uuid: UUID,
+ val version: String,
+ val main: String,
+)
diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt
index 30a8afd6a..915ad2fd3 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt
+++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt
@@ -48,6 +48,8 @@ import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent
import de.bixilon.minosoft.modding.event.events.loading.RegistriesLoadEvent
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
+import de.bixilon.minosoft.modding.loader.LoadingPhases
+import de.bixilon.minosoft.modding.loader.ModLoader
import de.bixilon.minosoft.protocol.network.connection.Connection
import de.bixilon.minosoft.protocol.network.connection.play.clientsettings.ClientSettingsManager
import de.bixilon.minosoft.protocol.network.connection.play.plugin.DefaultPluginHandler
@@ -168,6 +170,9 @@ class PlayConnection(
val count = latch.count
check(!wasConnected) { "Connection was already connected!" }
try {
+ state = PlayConnectionStates.WAITING_MODS
+ ModLoader.await(LoadingPhases.BOOT)
+
state = PlayConnectionStates.LOADING_ASSETS
var error: Throwable? = null
val taskWorker = TaskWorker(errorHandler = { _, exception -> if (error == null) error = exception }, criticalErrorHandler = { _, exception -> if (error == null) error = exception })
diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnectionStates.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnectionStates.kt
index a9e842244..65bc958d1 100644
--- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnectionStates.kt
+++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnectionStates.kt
@@ -22,6 +22,8 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
enum class PlayConnectionStates : Translatable {
WAITING,
+ WAITING_MODS,
+
LOADING_ASSETS,
LOADING,
diff --git a/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt b/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt
index bc704b674..742f619be 100644
--- a/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt
+++ b/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt
@@ -82,6 +82,10 @@ object CommandLineArguments {
addArgument("--ignore_yggdrasil")
.action(Arguments.storeTrue())
.help("Disable all yggdrasil (mojang) signature checking")
+
+ addArgument("--ignore_mods")
+ .action(Arguments.storeTrue())
+ .help("Ignores all mods and disable mod loading")
}
fun parse(args: Array) {
@@ -125,5 +129,6 @@ object CommandLineArguments {
RunConfiguration.VERBOSE_LOGGING = namespace.getBoolean("verbose")
RunConfiguration.IGNORE_YGGDRASIL = namespace.getBoolean("ignore_yggdrasil")
+ RunConfiguration.IGNORE_MODS = namespace.getBoolean("ignore_mods")
}
}
diff --git a/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt b/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt
index 339aa1b5a..507aea535 100644
--- a/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt
+++ b/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt
@@ -66,4 +66,6 @@ object RunConfiguration {
var IGNORE_YGGDRASIL = false
+
+ var IGNORE_MODS = false
}