mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 11:54:59 -04:00
improve mod list, virtual mods
This commit is contained in:
parent
e272fa83fc
commit
dbf461b393
67
src/main/java/de/bixilon/minosoft/modding/loader/ModList.kt
Normal file
67
src/main/java/de/bixilon/minosoft/modding/loader/ModList.kt
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.modding.loader
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.modding.loader.error.NoManifestError
|
||||||
|
import de.bixilon.minosoft.modding.loader.mod.MinosoftMod
|
||||||
|
|
||||||
|
class ModList(
|
||||||
|
val mods: MutableMap<String, MinosoftMod> = mutableMapOf(),
|
||||||
|
val virtual: MutableMap<String, MinosoftMod> = mutableMapOf(),
|
||||||
|
) : Iterable<MinosoftMod> {
|
||||||
|
|
||||||
|
inline operator fun minusAssign(mod: MinosoftMod) = remove(mod)
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun remove(mod: MinosoftMod) {
|
||||||
|
val manifest = mod.manifest ?: throw NoManifestError(mod.path)
|
||||||
|
this.mods -= manifest.name
|
||||||
|
this.virtual -= manifest.name
|
||||||
|
|
||||||
|
manifest.packages?.provides?.let { this.virtual -= it }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator fun plusAssign(mod: MinosoftMod) = add(mod)
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun add(mod: MinosoftMod) {
|
||||||
|
val manifest = mod.manifest ?: throw NoManifestError(mod.path)
|
||||||
|
|
||||||
|
this.mods[manifest.name] = mod
|
||||||
|
this.virtual[manifest.name] = mod
|
||||||
|
|
||||||
|
manifest.packages?.provides?.let {
|
||||||
|
for (name in it) {
|
||||||
|
this.virtual[name] = mod
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun contains(name: String): Boolean = get(name) != null
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
operator fun get(name: String): MinosoftMod? {
|
||||||
|
return mods[name] ?: virtual[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
operator fun plusAssign(list: ModList) {
|
||||||
|
this.mods += list.mods
|
||||||
|
this.virtual += list.virtual
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<MinosoftMod> {
|
||||||
|
return mods.values.iterator()
|
||||||
|
}
|
||||||
|
}
|
@ -22,10 +22,7 @@ import de.bixilon.minosoft.assets.directory.DirectoryAssetsManager
|
|||||||
import de.bixilon.minosoft.assets.file.ZipAssetsManager
|
import de.bixilon.minosoft.assets.file.ZipAssetsManager
|
||||||
import de.bixilon.minosoft.assets.util.FileUtil.readJson
|
import de.bixilon.minosoft.assets.util.FileUtil.readJson
|
||||||
import de.bixilon.minosoft.modding.loader.LoaderUtil.load
|
import de.bixilon.minosoft.modding.loader.LoaderUtil.load
|
||||||
import de.bixilon.minosoft.modding.loader.error.DuplicateModError
|
import de.bixilon.minosoft.modding.loader.error.*
|
||||||
import de.bixilon.minosoft.modding.loader.error.NoManifestError
|
|
||||||
import de.bixilon.minosoft.modding.loader.error.NoModMainError
|
|
||||||
import de.bixilon.minosoft.modding.loader.error.NoObjectMainError
|
|
||||||
import de.bixilon.minosoft.modding.loader.mod.MinosoftMod
|
import de.bixilon.minosoft.modding.loader.mod.MinosoftMod
|
||||||
import de.bixilon.minosoft.modding.loader.mod.ModMain
|
import de.bixilon.minosoft.modding.loader.mod.ModMain
|
||||||
import de.bixilon.minosoft.modding.loader.mod.manifest.load.LoadM
|
import de.bixilon.minosoft.modding.loader.mod.manifest.load.LoadM
|
||||||
@ -43,7 +40,7 @@ object ModLoader {
|
|||||||
private val BASE_PATH = RunConfiguration.HOME_DIRECTORY + "mods/"
|
private val BASE_PATH = RunConfiguration.HOME_DIRECTORY + "mods/"
|
||||||
private const val MANIFEST = "manifest.json"
|
private const val MANIFEST = "manifest.json"
|
||||||
private var latch: CountUpAndDownLatch? = null
|
private var latch: CountUpAndDownLatch? = null
|
||||||
val mods: MutableMap<String, MinosoftMod> = mutableMapOf()
|
val mods = ModList()
|
||||||
var currentPhase by watched(LoadingPhases.PRE_BOOT)
|
var currentPhase by watched(LoadingPhases.PRE_BOOT)
|
||||||
private set
|
private set
|
||||||
var state by watched(PhaseStates.WAITING)
|
var state by watched(PhaseStates.WAITING)
|
||||||
@ -137,7 +134,7 @@ object ModLoader {
|
|||||||
main!!.postInit()
|
main!!.postInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inject(mods: MutableMap<String, MinosoftMod>, file: File, phase: LoadingPhases, latch: CountUpAndDownLatch) {
|
private fun inject(list: ModList, file: File, phase: LoadingPhases, latch: CountUpAndDownLatch) {
|
||||||
if (!file.isDirectory && !file.name.endsWith(".jar") && !file.name.endsWith(".zip")) {
|
if (!file.isDirectory && !file.name.endsWith(".jar") && !file.name.endsWith(".zip")) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -149,11 +146,20 @@ object ModLoader {
|
|||||||
} else {
|
} else {
|
||||||
mod.processJar(file)
|
mod.processJar(file)
|
||||||
}
|
}
|
||||||
val name = mod.manifest!!.name
|
val manifest = mod.manifest!!
|
||||||
if (name in mods || name in this.mods) {
|
val name = manifest.name
|
||||||
|
if (name in list || name in this.mods) {
|
||||||
throw DuplicateModError(name)
|
throw DuplicateModError(name)
|
||||||
}
|
}
|
||||||
mods[name] = mod
|
manifest.packages?.provides?.let {
|
||||||
|
for (providedName in it) {
|
||||||
|
val provided = list[providedName] ?: this.mods[providedName]
|
||||||
|
if (provided != null) {
|
||||||
|
throw DuplicateProvidedError(mod, provided, providedName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list += mod
|
||||||
mod.latch.dec()
|
mod.latch.dec()
|
||||||
} catch (exception: Throwable) {
|
} catch (exception: Throwable) {
|
||||||
Log.log(LogMessageType.MOD_LOADING, LogLevels.WARN) { "Error injecting mod: $file" }
|
Log.log(LogMessageType.MOD_LOADING, LogLevels.WARN) { "Error injecting mod: $file" }
|
||||||
@ -186,18 +192,18 @@ object ModLoader {
|
|||||||
state = PhaseStates.COMPLETE
|
state = PhaseStates.COMPLETE
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val mods: MutableMap<String, MinosoftMod> = synchronizedMapOf()
|
val list = ModList(synchronizedMapOf(), synchronizedMapOf())
|
||||||
|
|
||||||
state = PhaseStates.INJECTING
|
state = PhaseStates.INJECTING
|
||||||
var worker = UnconditionalWorker()
|
var worker = UnconditionalWorker()
|
||||||
for (file in files) {
|
for (file in files) {
|
||||||
worker += add@{ inject(mods, file, phase, inner) }
|
worker += add@{ inject(list, file, phase, inner) }
|
||||||
}
|
}
|
||||||
worker.work(inner)
|
worker.work(inner)
|
||||||
|
|
||||||
state = PhaseStates.CONSTRUCTING
|
state = PhaseStates.CONSTRUCTING
|
||||||
worker = UnconditionalWorker()
|
worker = UnconditionalWorker()
|
||||||
for ((name, mod) in mods) {
|
for (mod in list) {
|
||||||
worker += {
|
worker += {
|
||||||
try {
|
try {
|
||||||
mod.construct()
|
mod.construct()
|
||||||
@ -205,7 +211,7 @@ object ModLoader {
|
|||||||
} catch (error: Throwable) {
|
} catch (error: Throwable) {
|
||||||
mod.latch.count = 0
|
mod.latch.count = 0
|
||||||
error.printStackTrace()
|
error.printStackTrace()
|
||||||
mods -= name
|
list -= mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,7 +219,7 @@ object ModLoader {
|
|||||||
|
|
||||||
state = PhaseStates.POST_INIT
|
state = PhaseStates.POST_INIT
|
||||||
worker = UnconditionalWorker()
|
worker = UnconditionalWorker()
|
||||||
for ((name, mod) in mods) {
|
for (mod in list) {
|
||||||
worker += {
|
worker += {
|
||||||
try {
|
try {
|
||||||
mod.postInit()
|
mod.postInit()
|
||||||
@ -221,14 +227,14 @@ object ModLoader {
|
|||||||
} catch (error: Throwable) {
|
} catch (error: Throwable) {
|
||||||
mod.latch.count = 0
|
mod.latch.count = 0
|
||||||
error.printStackTrace()
|
error.printStackTrace()
|
||||||
mods -= name
|
list -= mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
worker.work(inner)
|
worker.work(inner)
|
||||||
|
|
||||||
|
|
||||||
this.mods += mods
|
this.mods += list
|
||||||
state = PhaseStates.COMPLETE
|
state = PhaseStates.COMPLETE
|
||||||
inner.dec()
|
inner.dec()
|
||||||
if (phase == LoadingPhases.POST_BOOT) {
|
if (phase == LoadingPhases.POST_BOOT) {
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.bixilon.minosoft.modding.loader.error
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.modding.loader.mod.MinosoftMod
|
||||||
|
|
||||||
|
class DuplicateProvidedError(
|
||||||
|
val mod: MinosoftMod,
|
||||||
|
val providedBy: MinosoftMod,
|
||||||
|
val virtualName: String,
|
||||||
|
) : Exception("${mod.manifest?.name} provides $virtualName, but already provided by ${providedBy.manifest?.name}!")
|
Loading…
x
Reference in New Issue
Block a user