Skip to content

Commit cc5b6b5

Browse files
committed
overhaul with new api
1 parent 391b59b commit cc5b6b5

19 files changed

Lines changed: 256 additions & 85 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea
22
.gradle
33
build
4+
run

src/main/kotlin/org/bundleproject/bundle/Bundle.kt

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import kotlinx.coroutines.async
88
import kotlinx.coroutines.awaitAll
99
import kotlinx.coroutines.runBlocking
1010
import org.bundleproject.bundle.entities.Mod
11-
import org.bundleproject.bundle.entities.platform.Platform
11+
import org.bundleproject.bundle.api.data.Platform
12+
import org.bundleproject.bundle.api.requests.BulkModRequest
13+
import org.bundleproject.bundle.entities.RemoteMod
1214
import org.bundleproject.bundle.gui.LoadingGui
1315
import org.bundleproject.bundle.gui.UpdateOverviewGui
1416
import org.bundleproject.bundle.utils.*
@@ -36,18 +38,20 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
3638

3739
suspend fun start() {
3840
try {
41+
println("Starting Bundle...")
3942
try { UIManager.setLookAndFeel(FlatLightLaf()) }
4043
catch (e: Throwable) { e.printStackTrace() }
4144

42-
checkOutdated()
4345
val outdated = getOutdatedMods()
4446

4547
if (outdated.isEmpty()) return
4648

4749
val lock = ReentrantLock()
4850
val condition = lock.newCondition()
4951
lock.withLock {
50-
UpdateOverviewGui(this, outdated, condition)
52+
UpdateOverviewGui(this, outdated, condition).apply {
53+
isVisible = true
54+
}
5155
condition.await()
5256
}
5357

@@ -59,22 +63,34 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
5963
/**
6064
* Walks through the mods and looks through each file
6165
* and attempts to check if it's a valid mod
62-
* and if it's out of date
66+
*
67+
* All the valid mods are collected into a list before
68+
* bulk-requesting the latest versions from the API.
69+
* They are matched into pairs and returned.
6370
*
6471
* @since 0.0.1
6572
*/
66-
private fun getOutdatedMods(): MutableList<Pair<Mod, Mod>> {
67-
val outdated = mutableListOf<Pair<Mod, Mod>>()
73+
private suspend fun getOutdatedMods(): MutableList<Pair<Mod, RemoteMod>> {
74+
val localMods = mutableListOf<Mod>()
6875
for (mod in modsDir.walkTopDown()) {
76+
if (mod.isDirectory) continue
77+
6978
val localMod = getModInfo(mod) ?: continue
70-
if (localMod.version != version) continue
79+
if (localMod.minecraftVersion != version) continue
80+
81+
localMods.add(localMod)
82+
}
7183

72-
val remoteMod = runBlocking { Mod.fromUrl(localMod.latestUrl) }
84+
val request = BulkModRequest(localMods.map { it.makeRequest() })
85+
val response = request.request()
7386

74-
// out of date
75-
if (remoteMod.version.greaterThan(localMod.version)) {
76-
outdated.add(Pair(localMod, remoteMod))
77-
}
87+
val outdated = mutableListOf<Pair<Mod, RemoteMod>>()
88+
for (i in localMods.indices) {
89+
val local = localMods[i]
90+
val remote = local.applyData(response[i])
91+
92+
if (remote > local)
93+
outdated.add(local to remote)
7894
}
7995

8096
return outdated
@@ -138,12 +154,12 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
138154

139155

140156
/**
141-
* Goes through a list of mods and linearly deletes
157+
* Goes through a list of mods and asynchronously deletes
142158
* and replaces it with its updated counterpart
143159
*
144160
* @since 0.0.2
145161
*/
146-
fun updateMods(mods: List<Pair<Mod, Mod>>) {
162+
fun updateMods(mods: List<Pair<Mod, RemoteMod>>) {
147163
launchCoroutine("Mod Updater") {
148164
val loading = LoadingGui(mods.size)
149165
loading.isVisible = true
@@ -152,26 +168,12 @@ class Bundle(private val gameDir: File, private val version: Version, modFolderN
152168
val current = File(modsDir, local.fileName)
153169

154170
Files.delete(current.toPath())
155-
runBlocking { URL(remote.latestDownloadUrl) }
171+
runBlocking { URL(remote.downloadUrl) }
156172
.download(File(modsDir, remote.fileName))
157173
loading.finish()
158174
}
159175
}.awaitAll()
160176
}
161177

162178
}
163-
164-
/**
165-
* Checks if Bundle is outdated.
166-
*
167-
* @since 0.0.3
168-
*/
169-
private suspend fun checkOutdated() {
170-
val versions = JsonParser.parseString(http.get<String>("$API/$API_VERSION/bundle/version")).asJsonObject
171-
172-
if (Version.valueOf(versions.get("updater").asString).greaterThan(VERSION)) {
173-
JOptionPane.showMessageDialog(null, "Bundle is outdated. Please re-run the installer to get the update!", "Bundle", JOptionPane.WARNING_MESSAGE)
174-
}
175-
}
176-
177179
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.bundleproject.bundle.api.data
2+
3+
import com.github.zafarkhaja.semver.Version
4+
5+
data class ModData(
6+
val url: String,
7+
val version: Version,
8+
val metadata: Metadata,
9+
) {
10+
data class Metadata(
11+
val display: String,
12+
val creator: String,
13+
)
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.bundleproject.bundle.api.data
2+
3+
enum class Platform(val id: String) {
4+
Forge("forge"),
5+
Fabric("fabric");
6+
7+
override fun toString(): String {
8+
return id
9+
}
10+
11+
companion object {
12+
fun fromId(id: String): Platform? =
13+
values().find { it.id == id }
14+
}
15+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.bundleproject.bundle.api.requests
2+
3+
import com.google.gson.JsonArray
4+
import com.google.gson.JsonObject
5+
import io.ktor.client.request.*
6+
import org.bundleproject.bundle.api.data.ModData
7+
import org.bundleproject.bundle.api.responses.BulkModResponse
8+
import org.bundleproject.bundle.utils.*
9+
10+
data class BulkModRequest(
11+
val mods: List<ModRequest>
12+
) {
13+
suspend fun request(): List<ModData> {
14+
val json = JsonArray().apply {
15+
mods.forEach { add(gson.toJsonTree(it)) }
16+
}
17+
18+
val base64 = gson.toJson(json).encodeBase64()
19+
return http.get<BulkModResponse>("$API/$API_VERSION/mods/bulk/$base64").mods
20+
}
21+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.bundleproject.bundle.api.requests
2+
3+
import io.ktor.client.request.*
4+
import org.bundleproject.bundle.api.data.ModData
5+
import org.bundleproject.bundle.api.responses.ModResponse
6+
import org.bundleproject.bundle.api.data.Platform
7+
import org.bundleproject.bundle.utils.API
8+
import org.bundleproject.bundle.utils.API_VERSION
9+
import org.bundleproject.bundle.utils.http
10+
11+
data class ModRequest(
12+
val id: String,
13+
val platform: Platform,
14+
val minecraftVersion: String,
15+
val version: String = "latest",
16+
) {
17+
constructor(
18+
id: String,
19+
platform: String,
20+
minecraftVersion: String,
21+
version: String = "latest",
22+
) : this(id, Platform.fromId(platform)!!, minecraftVersion, version)
23+
24+
@Transient
25+
val endpoint = "$API/$API_VERSION/mods/$id/$platform/$minecraftVersion/$version"
26+
27+
suspend fun request(): ModData {
28+
return http.get<ModResponse>(endpoint).data
29+
}
30+
}
31+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.bundleproject.bundle.api.responses
2+
3+
import org.bundleproject.bundle.api.data.ModData
4+
5+
data class BulkModResponse(
6+
val success: Boolean,
7+
val mods: List<ModData>,
8+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.bundleproject.bundle.api.responses
2+
3+
data class ErrorResponse(
4+
val success: Boolean,
5+
val error: String,
6+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.bundleproject.bundle.api.responses
2+
3+
import org.bundleproject.bundle.api.data.ModData
4+
5+
data class ModResponse(
6+
val success: Boolean,
7+
val data: ModData,
8+
)
Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package org.bundleproject.bundle.entities
22

33
import com.github.zafarkhaja.semver.Version
4-
import io.ktor.client.request.*
5-
import org.bundleproject.bundle.entities.platform.Platform
6-
import org.bundleproject.bundle.utils.API
7-
import org.bundleproject.bundle.utils.API_VERSION
8-
import org.bundleproject.bundle.utils.http
4+
import org.bundleproject.bundle.api.data.ModData
5+
import org.bundleproject.bundle.api.data.Platform
6+
import org.bundleproject.bundle.api.requests.ModRequest
97

10-
data class Mod(
8+
open class Mod(
119
@Transient var enabled: Boolean = true,
1210
val name: String,
1311
val id: String,
@@ -16,15 +14,29 @@ data class Mod(
1614
val fileName: String,
1715
val platform: Platform,
1816
) {
19-
@Transient
20-
val latestUrl = "$API/$API_VERSION/mods/$id/$platform/$minecraftVersion/latest/"
21-
@Transient
22-
val latestDownloadUrl = latestUrl + "download"
17+
val downloadEndpoint = "${makeRequest().endpoint}/download"
2318

24-
companion object {
25-
suspend fun fromUrl(url: String): Mod {
26-
return http.get(url)
27-
}
19+
fun makeRequest(): ModRequest =
20+
ModRequest(id, platform, minecraftVersion.toString())
21+
22+
fun applyData(data: ModData): RemoteMod {
23+
return RemoteMod(
24+
enabled,
25+
name,
26+
id,
27+
data.version,
28+
minecraftVersion,
29+
fileName,
30+
platform,
31+
data.url,
32+
)
33+
}
34+
35+
suspend fun latest(): RemoteMod {
36+
return applyData(makeRequest().request())
2837
}
2938

39+
operator fun compareTo(other: Mod): Int {
40+
return version.compareTo(other.version)
41+
}
3042
}

0 commit comments

Comments
 (0)