11package org.bundleproject.bundle
22
33import com.formdev.flatlaf.FlatLightLaf
4- import com.github.zafarkhaja.semver.Version
54import com.google.gson.JsonParser
6- import io.ktor.client.request.*
75import kotlinx.coroutines.async
86import kotlinx.coroutines.awaitAll
7+ import kotlinx.coroutines.coroutineScope
98import kotlinx.coroutines.runBlocking
109import org.bundleproject.bundle.entities.Mod
1110import org.bundleproject.bundle.api.data.Platform
1211import org.bundleproject.bundle.api.requests.BulkModRequest
13- import org.bundleproject.bundle.entities.RemoteMod
1412import org.bundleproject.bundle.gui.LoadingGui
1513import org.bundleproject.bundle.gui.UpdateOverviewGui
1614import org.bundleproject.bundle.utils.*
@@ -32,27 +30,31 @@ import kotlin.concurrent.withLock
3230 *
3331 * @since 0.0.1
3432 */
35- class Bundle (private val gameDir : File , private val version : Version , modFolderName : String ) {
33+ class Bundle (private val gameDir : File , private val version : Version ? , modFolderName : String ) {
3634 private val modsDir = File (gameDir, modFolderName)
3735
3836 suspend fun start () {
3937 try {
40- println (" Starting Bundle..." )
38+ info(" Starting Bundle..." )
39+ println ()
40+
4141 try { UIManager .setLookAndFeel(FlatLightLaf ()) }
4242 catch (e: Throwable ) { e.printStackTrace() }
4343
4444 val outdated = getOutdatedMods()
4545
4646 if (outdated.isEmpty()) return
4747
48- val lock = ReentrantLock ()
49- val condition = lock.newCondition()
50- lock.withLock {
51- UpdateOverviewGui (this , outdated, condition).apply {
52- isVisible = true
53- }
54- condition.await()
55- }
48+ // val lock = ReentrantLock()
49+ // val condition = lock.newCondition()
50+ // lock.withLock {
51+ // UpdateOverviewGui(this, outdated, condition).apply {
52+ // isVisible = true
53+ // }
54+ // condition.await()
55+ // }
56+
57+ updateMods(outdated)
5658
5759 } catch (e: Throwable ) {
5860 e.printStackTrace()
@@ -70,19 +72,33 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
7072 * @since 0.0.1
7173 */
7274 private suspend fun getOutdatedMods (): MutableList <ModPair > {
75+ info(" Getting outdated mods..." )
76+
7377 val localMods = mutableListOf<Mod >()
7478 for (mod in modsDir.walkTopDown()) {
7579 if (mod.isDirectory) continue
7680
77- val localMod = getModInfo(mod) ? : continue
78- if (localMod.minecraftVersion != version) continue
81+ val localMod = try {
82+ getModInfo(mod)
83+ } catch (e: Exception ) {
84+ if (e is Version .VersionParseException ) err(" Failed to parse version for ${mod.name} " )
85+ else e.printStackTrace()
86+
87+ null
88+ } ? : continue
89+
90+ if (localMod.minecraftVersion != (version ? : localMod.minecraftVersion)) continue
7991
8092 localMods.add(localMod)
8193 }
94+ info(" Found: ${localMods.map { it.id }.toFormattedString()} " )
95+ println ()
8296
97+ info(" Making bulk request to API." )
8398 val request = BulkModRequest (localMods.map { it.makeRequest() })
8499 val response = request.request()
85100
101+ info(" Comparing local to remote mod versions." )
86102 val outdated = mutableListOf<ModPair >()
87103 for (i in localMods.indices) {
88104 val local = localMods[i]
@@ -91,6 +107,9 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
91107 if (remote > local)
92108 outdated.add(ModPair (local, remote))
93109 }
110+ info(" ${outdated.size} /${localMods.size} mods need an update." )
111+ info(" Outdated: ${outdated.map { it.remote.id }.toFormattedString()} " )
112+ println ()
94113
95114 return outdated
96115 }
@@ -101,8 +120,11 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
101120 * @since 0.0.1
102121 */
103122 private fun getModInfo (modFile : File ): Mod ? {
123+ info(" Getting mod info using method: " , false )
104124 JarFile (modFile).use { jar ->
105125 jar.getJarEntry(" bundle.project.json" )?.let getJarEntry@{ modInfo ->
126+ info(" Bundle Info File" )
127+
106128 InputStreamReader (jar.getInputStream(modInfo)).use {
107129 val json = JsonParser .parseReader(it).asJsonObject
108130
@@ -111,43 +133,48 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
111133 return @getModInfo Mod (
112134 name = json.get(" name" )?.asString ? : return null ,
113135 id = json.get(" id" )?.asString ? : return @getJarEntry,
114- version = Version .valueOf (json.get(" version" )?.asString ? : return @getJarEntry),
115- minecraftVersion = Version .valueOf (json.get(" minecraft_version" )?.asString ? : return @getJarEntry),
136+ version = Version .of (json.get(" version" )?.asString ? : return @getJarEntry),
137+ minecraftVersion = Version .of (json.get(" minecraft_version" )?.asString ? : return @getJarEntry),
116138 fileName = modFile.name,
117139 platform = Platform .valueOf(json.get(" platform" )?.asString?.uppercase() ? : return @getJarEntry),
118140 )
119141 }
120142 }
121143
122144 jar.getJarEntry(" fabric.mod.json" )?.let { modInfo ->
145+ info(" Fabric Info File" )
146+
123147 InputStreamReader (jar.getInputStream(modInfo)).use {
124148 val json = JsonParser .parseReader(it).asJsonObject
125149 return @getModInfo Mod (
126150 name = json.get(" name" )?.asString ? : return null ,
127151 id = json.get(" id" )?.asString ? : return null ,
128- version = Version .valueOf (json.get(" version" )?.asString ? : return null ),
129- minecraftVersion = Version .valueOf (json.get(" depends" ).asJsonObject.get(" minecraft" )?.asString ? : return null ),
152+ version = Version .of (json.get(" version" )?.asString ? : return null ),
153+ minecraftVersion = Version .of (json.get(" depends" ).asJsonObject.get(" minecraft" )?.asString ? : return null ),
130154 fileName = modFile.name,
131155 platform = Platform .Fabric ,
132156 )
133157 }
134158 }
135159
136160 jar.getJarEntry(" mcmod.info" )?.let { modInfo ->
161+ info(" Forge Info File" )
162+
137163 InputStreamReader (jar.getInputStream(modInfo)).use {
138164 val json = JsonParser .parseReader(it).asJsonArray[0 ].asJsonObject
139165 return @getModInfo Mod (
140166 name = json.get(" name" )?.asString ? : return null ,
141167 id = json.get(" modid" )?.asString ? : return null ,
142- version = Version .valueOf (json.get(" version" )?.asString ? : return null ),
143- minecraftVersion = Version .valueOf (json.get(" mcversion" )?.asString ? : return null ),
168+ version = Version .of (json.get(" version" )?.asString ? : return null ),
169+ minecraftVersion = Version .of (json.get(" mcversion" )?.asString ? : return null ),
144170 fileName = modFile.name,
145171 platform = Platform .Forge ,
146172 )
147173 }
148174 }
149175 }
150176
177+ err(" None" )
151178 return null
152179 }
153180
@@ -158,17 +185,25 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
158185 *
159186 * @since 0.0.2
160187 */
161- fun updateMods (mods : List <ModPair >) {
162- launchCoroutine(" Mod Updater" ) {
188+ suspend fun updateMods (mods : List <ModPair >) {
189+ info(" Updating Mods..." )
190+
191+ coroutineScope {
163192 val loading = LoadingGui (mods.size)
164193 loading.isVisible = true
165194 mods.map { (local, remote) ->
166195 async {
167196 val current = File (modsDir, local.fileName)
197+ val new = File (modsDir, remote.fileName)
198+
199+ info(" Downloading: ${new.name} " )
200+ if (http.downloadFile(new, remote.downloadEndpoint)) {
201+ info(" Deleting: ${current.name} " )
202+ current.delete()
203+ } else {
204+ error(" Failed to download! Skipping!" )
205+ }
168206
169- Files .delete(current.toPath())
170- runBlocking { URL (remote.downloadUrl) }
171- .download(File (modsDir, remote.fileName))
172207 loading.finish()
173208 }
174209 }.awaitAll()
0 commit comments