mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 03:15:35 -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.util.FileUtil.readJson
|
||||
import de.bixilon.minosoft.modding.loader.LoaderUtil.load
|
||||
import de.bixilon.minosoft.modding.loader.error.DuplicateModError
|
||||
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.error.*
|
||||
import de.bixilon.minosoft.modding.loader.mod.MinosoftMod
|
||||
import de.bixilon.minosoft.modding.loader.mod.ModMain
|
||||
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 const val MANIFEST = "manifest.json"
|
||||
private var latch: CountUpAndDownLatch? = null
|
||||
val mods: MutableMap<String, MinosoftMod> = mutableMapOf()
|
||||
val mods = ModList()
|
||||
var currentPhase by watched(LoadingPhases.PRE_BOOT)
|
||||
private set
|
||||
var state by watched(PhaseStates.WAITING)
|
||||
@ -137,7 +134,7 @@ object ModLoader {
|
||||
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")) {
|
||||
return
|
||||
}
|
||||
@ -149,11 +146,20 @@ object ModLoader {
|
||||
} else {
|
||||
mod.processJar(file)
|
||||
}
|
||||
val name = mod.manifest!!.name
|
||||
if (name in mods || name in this.mods) {
|
||||
val manifest = mod.manifest!!
|
||||
val name = manifest.name
|
||||
if (name in list || name in this.mods) {
|
||||
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()
|
||||
} catch (exception: Throwable) {
|
||||
Log.log(LogMessageType.MOD_LOADING, LogLevels.WARN) { "Error injecting mod: $file" }
|
||||
@ -186,18 +192,18 @@ object ModLoader {
|
||||
state = PhaseStates.COMPLETE
|
||||
return
|
||||
}
|
||||
val mods: MutableMap<String, MinosoftMod> = synchronizedMapOf()
|
||||
val list = ModList(synchronizedMapOf(), synchronizedMapOf())
|
||||
|
||||
state = PhaseStates.INJECTING
|
||||
var worker = UnconditionalWorker()
|
||||
for (file in files) {
|
||||
worker += add@{ inject(mods, file, phase, inner) }
|
||||
worker += add@{ inject(list, file, phase, inner) }
|
||||
}
|
||||
worker.work(inner)
|
||||
|
||||
state = PhaseStates.CONSTRUCTING
|
||||
worker = UnconditionalWorker()
|
||||
for ((name, mod) in mods) {
|
||||
for (mod in list) {
|
||||
worker += {
|
||||
try {
|
||||
mod.construct()
|
||||
@ -205,7 +211,7 @@ object ModLoader {
|
||||
} catch (error: Throwable) {
|
||||
mod.latch.count = 0
|
||||
error.printStackTrace()
|
||||
mods -= name
|
||||
list -= mod
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,7 +219,7 @@ object ModLoader {
|
||||
|
||||
state = PhaseStates.POST_INIT
|
||||
worker = UnconditionalWorker()
|
||||
for ((name, mod) in mods) {
|
||||
for (mod in list) {
|
||||
worker += {
|
||||
try {
|
||||
mod.postInit()
|
||||
@ -221,14 +227,14 @@ object ModLoader {
|
||||
} catch (error: Throwable) {
|
||||
mod.latch.count = 0
|
||||
error.printStackTrace()
|
||||
mods -= name
|
||||
list -= mod
|
||||
}
|
||||
}
|
||||
}
|
||||
worker.work(inner)
|
||||
|
||||
|
||||
this.mods += mods
|
||||
this.mods += list
|
||||
state = PhaseStates.COMPLETE
|
||||
inner.dec()
|
||||
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