diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt b/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt index c46a6c807..47f70ba9e 100644 --- a/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt +++ b/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt @@ -210,7 +210,6 @@ object ModLoader { state = PhaseStates.VALIDATING worker = UnconditionalWorker() - val invalid: MutableSet = mutableSetOf() for (mod in list) { worker += { try { @@ -219,16 +218,16 @@ object ModLoader { } catch (error: Throwable) { mod.latch.count = 0 error.printStackTrace() - invalid += mod + list -= mod } } } worker.work(inner) - list -= invalid + val sorted = list.sorted().toMutableList() state = PhaseStates.CONSTRUCTING worker = UnconditionalWorker() - for (mod in list) { + for (mod in sorted) { worker += { try { mod.construct() @@ -237,6 +236,7 @@ object ModLoader { mod.latch.count = 0 error.printStackTrace() list -= mod + sorted -= mod } } } @@ -244,7 +244,7 @@ object ModLoader { state = PhaseStates.POST_INIT worker = UnconditionalWorker() - for (mod in list) { + for (mod in sorted) { worker += { try { mod.postInit() @@ -253,6 +253,7 @@ object ModLoader { mod.latch.count = 0 error.printStackTrace() list -= mod + sorted -= mod } } } 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 index 9092531fe..b003b121f 100644 --- a/src/main/java/de/bixilon/minosoft/modding/loader/mod/MinosoftMod.kt +++ b/src/main/java/de/bixilon/minosoft/modding/loader/mod/MinosoftMod.kt @@ -25,7 +25,7 @@ class MinosoftMod( val path: File, val phase: LoadingPhases, val latch: CountUpAndDownLatch, -) { +) : Comparable { val classLoader = JarClassLoader() var manifest: ModManifest? = null var assetsManager: AssetsManager? = null @@ -41,4 +41,25 @@ class MinosoftMod( error.printStackTrace() } } + + override fun compareTo(other: MinosoftMod): Int { + val manifest = manifest!! + val otherManifest = other.manifest!! + + val depends: MutableSet = mutableSetOf() + manifest.packages?.depends?.let { depends += it } + manifest.load?.after?.let { depends += it } + + if (otherManifest.name in depends) { + return 1 // load before + } + + manifest.load?.before?.let { + if (otherManifest.name in it) { + return -1 + } + } + + return 0 + } } diff --git a/src/test/java/de/bixilon/minosoft/modding/loader/mod/MinosoftModTest.kt b/src/test/java/de/bixilon/minosoft/modding/loader/mod/MinosoftModTest.kt new file mode 100644 index 000000000..bb5b4cdc0 --- /dev/null +++ b/src/test/java/de/bixilon/minosoft/modding/loader/mod/MinosoftModTest.kt @@ -0,0 +1,121 @@ +/* + * 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.modding.loader.LoadingPhases +import de.bixilon.minosoft.modding.loader.ModList +import de.bixilon.minosoft.modding.loader.mod.manifest.ModManifest +import de.bixilon.minosoft.modding.loader.mod.manifest.load.LoadM +import de.bixilon.minosoft.modding.loader.mod.manifest.packages.PackagesM +import java.io.File +import kotlin.test.Test +import kotlin.test.assertEquals + +internal class MinosoftModTest { + + private fun createMod(): MinosoftMod { + return MinosoftMod(File("."), LoadingPhases.PRE_BOOT, CountUpAndDownLatch(0)) + } + + @Test + fun testDependsOn1() { + val dependency = createMod().apply { manifest = ModManifest("dependency", version = "0", main = "") } + val b = createMod().apply { manifest = ModManifest("bbb", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + val c = createMod().apply { manifest = ModManifest("ccc", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + + val list = ModList() + list += dependency + list += b + list += c + + + assertEquals(list.sorted(), mutableListOf(dependency, b, c)) + } + + @Test + fun testDependsOn2() { + val dependency = createMod().apply { manifest = ModManifest("dependency", version = "0", main = "") } + val b = createMod().apply { manifest = ModManifest("bbb", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + val c = createMod().apply { manifest = ModManifest("ccc", version = "0", main = "", packages = PackagesM(setOf("dependency", "ccc"))) } + + val list = ModList() + list += dependency + list += b + list += c + + + assertEquals(list.sorted(), mutableListOf(dependency, b, c)) + } + + @Test + fun testDependsOn3() { + val dependency = createMod().apply { manifest = ModManifest("dependency", version = "0", main = "") } + val c = createMod().apply { manifest = ModManifest("ccc", version = "0", main = "", packages = PackagesM(setOf("dependency", "bbb"))) } + val b = createMod().apply { manifest = ModManifest("bbb", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + + val list = ModList() + list += dependency + list += b + list += c + + + assertEquals(list.sorted(), mutableListOf(dependency, b, c)) + } + + @Test + fun testDependsOn4() { + val dependency = createMod().apply { manifest = ModManifest("dependency", version = "0", main = "") } + val b = createMod().apply { manifest = ModManifest("bbb", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + val c = createMod().apply { manifest = ModManifest("ccc", version = "0", main = "", packages = PackagesM(setOf("bbb"))) } + + val list = ModList() + list += dependency + list += b + list += c + + + assertEquals(list.sorted(), mutableListOf(dependency, b, c)) + } + + @Test + fun testLoadingOrder1() { + val dependency = createMod().apply { manifest = ModManifest("dependency", version = "0", main = "") } + val c = createMod().apply { manifest = ModManifest("ccc", version = "0", main = "", load = LoadM(after = setOf("bbb"))) } + val b = createMod().apply { manifest = ModManifest("bbb", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + + val list = ModList() + list += dependency + list += b + list += c + + + assertEquals(list.sorted(), mutableListOf(dependency, b, c)) + } + + @Test + fun testLoadingOrder2() { + val dependency = createMod().apply { manifest = ModManifest("dependency", version = "0", main = "") } + val c = createMod().apply { manifest = ModManifest("ccc", version = "0", main = "", load = LoadM(before = setOf("bbb"))) } + val b = createMod().apply { manifest = ModManifest("bbb", version = "0", main = "", packages = PackagesM(setOf("dependency"))) } + + val list = ModList() + list += dependency + list += b + list += c + + + assertEquals(list.sorted(), mutableListOf(dependency, c, b)) + } +}