Skip to content
This repository was archived by the owner on Dec 30, 2022. It is now read-only.

Commit 62efc8e

Browse files
authored
Merge pull request #64 from DeathsGun/bugs/52_uptodate_marked_outdated
Add fallback for versions not following SemVer
2 parents 005d9df + 4c84b03 commit 62efc8e

File tree

16 files changed

+3884
-48
lines changed

16 files changed

+3884
-48
lines changed

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ plugins {
2020
id "fabric-loom" version "0.9-SNAPSHOT"
2121
id "com.modrinth.minotaur" version "1.2.1"
2222
id "org.jetbrains.kotlin.jvm" version "1.5.30"
23-
id 'org.jetbrains.kotlin.plugin.serialization' version '1.5.30'
23+
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.30"
2424
}
2525

2626
sourceCompatibility = JavaVersion.VERSION_16
@@ -42,10 +42,11 @@ dependencies {
4242
minecraft "com.mojang:minecraft:${project.minecraft_version}"
4343
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
4444
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
45+
4546
modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}"
4647
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
4748

48-
testImplementation 'org.jetbrains.kotlin:kotlin-test:1.5.21'
49+
testImplementation 'org.jetbrains.kotlin:kotlin-test:1.5.31'
4950
}
5051

5152
processResources {

src/main/kotlin/xyz/deathsgun/modmanager/ModManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class ModManager : ClientModInitializer {
5656

5757
@JvmStatic
5858
fun getMinecraftVersion(): String {
59-
return MinecraftClient.getInstance()?.game?.version?.releaseTarget ?: "1.17.1"
59+
return MinecraftClient.getInstance()?.game?.version?.name ?: "1.17.1"
6060
}
6161
}
6262

src/main/kotlin/xyz/deathsgun/modmanager/api/mod/Version.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616

1717
package xyz.deathsgun.modmanager.api.mod
1818

19+
import java.time.LocalDate
20+
1921
data class Version(
2022
val version: String,
2123
val changelog: String,
24+
val releaseDate: LocalDate,
2225
val type: VersionType,
2326
val gameVersions: List<String>,
2427
val assets: List<Asset>

src/main/kotlin/xyz/deathsgun/modmanager/config/Config.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ data class Config(
6969
fun text(): Text {
7070
return TranslatableText(String.format("modmanager.channel.%s", name.lowercase()))
7171
}
72-
}
7372

74-
fun isReleaseAllowed(type: VersionType): Boolean {
75-
if (updateChannel == UpdateChannel.ALL) {
76-
return true
77-
}
78-
if (updateChannel == UpdateChannel.STABLE && type == VersionType.RELEASE) {
79-
return true
73+
fun isReleaseAllowed(type: VersionType): Boolean {
74+
if (this == ALL) {
75+
return true
76+
}
77+
if (this == STABLE && type == VersionType.RELEASE) {
78+
return true
79+
}
80+
return this == UNSTABLE
8081
}
81-
return updateChannel == UpdateChannel.UNSTABLE
8282
}
8383
}

src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/Modrinth.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ import java.net.http.HttpClient
3939
import java.net.http.HttpRequest
4040
import java.net.http.HttpResponse
4141
import java.time.Duration
42+
import java.time.Instant
43+
import java.time.ZoneOffset
4244

4345
@OptIn(ExperimentalSerializationApi::class)
4446
class Modrinth : IModProvider, IModUpdateProvider {
@@ -211,6 +213,10 @@ class Modrinth : IModProvider, IModUpdateProvider {
211213
Version(
212214
modVersion.version,
213215
modVersion.changelog,
216+
// 2021-09-03T10:56:59.402790Z
217+
Instant.parse(modVersion.releaseDate).atOffset(
218+
ZoneOffset.UTC
219+
).toLocalDate(),
214220
getVersionType(modVersion.type),
215221
modVersion.gameVersions,
216222
assets

src/main/kotlin/xyz/deathsgun/modmanager/providers/modrinth/models/ModrinthVersion.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ data class ModrinthVersion(
2424
@SerialName("version_number")
2525
val version: String,
2626
val changelog: String,
27+
@SerialName("date_published")
28+
val releaseDate: String,
2729
@SerialName("version_type")
2830
val type: String,
2931
@SerialName("game_versions")

src/main/kotlin/xyz/deathsgun/modmanager/update/UpdateManager.kt

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ import kotlinx.serialization.ExperimentalSerializationApi
2323
import kotlinx.serialization.decodeFromString
2424
import kotlinx.serialization.json.Json
2525
import net.fabricmc.loader.api.FabricLoader
26-
import net.fabricmc.loader.api.SemanticVersion
2726
import net.fabricmc.loader.api.metadata.ModMetadata
28-
import net.fabricmc.loader.util.version.VersionDeserializer
2927
import net.minecraft.text.TranslatableText
3028
import org.apache.commons.io.FileUtils
3129
import org.apache.logging.log4j.LogManager
@@ -99,7 +97,12 @@ class UpdateManager {
9997
}
10098
var result = updateProvider.getVersionsForMod(metadata.id)
10199
if (result is VersionResult.Success) {
102-
val version = findLatestCompatible(metadata.version.friendlyString, result.versions)
100+
val version = VersionFinder.findUpdate(
101+
metadata.version.friendlyString,
102+
ModManager.getMinecraftVersion(),
103+
ModManager.modManager.config.updateChannel,
104+
result.versions
105+
)
103106
if (version == null) {
104107
logger.info("No update for {} found!", metadata.id)
105108
ModManager.modManager.setModState(metadata.id, metadata.id, ModState.INSTALLED)
@@ -117,7 +120,12 @@ class UpdateManager {
117120

118121
val queryResult = provider.search(metadata.name, Sorting.RELEVANCE, 0, 10)
119122
if (queryResult is ModsResult.Error) {
120-
logger.warn("Error while searching for fallback id for mod {}: ", metadata.id, queryResult.cause)
123+
logger.warn(
124+
"Error while searching for fallback id for mod {}: {}",
125+
metadata.id,
126+
queryResult.text.key,
127+
queryResult.cause
128+
)
121129
ModManager.modManager.setModState(metadata.id, metadata.id, ModState.INSTALLED)
122130
return
123131
}
@@ -136,13 +144,18 @@ class UpdateManager {
136144
result = updateProvider.getVersionsForMod(mod.id)
137145
val versions = when (result) {
138146
is VersionResult.Error -> {
139-
logger.error("Error while getting versions for mod {}", metadata.id)
147+
logger.error("Error while getting versions for mod {}", metadata.id, result.cause)
140148
ModManager.modManager.setModState(metadata.id, mod.id, ModState.INSTALLED)
141149
return
142150
}
143151
is VersionResult.Success -> result.versions
144152
}
145-
val version = findLatestCompatible(metadata.version.friendlyString, versions)
153+
val version = VersionFinder.findUpdate(
154+
metadata.version.friendlyString,
155+
ModManager.getMinecraftVersion(),
156+
ModManager.modManager.config.updateChannel,
157+
versions
158+
)
146159
if (version == null) {
147160
logger.info("No update for {} found!", metadata.id)
148161
ModManager.modManager.setModState(metadata.id, mod.id, ModState.INSTALLED)
@@ -177,13 +190,18 @@ class UpdateManager {
177190
}
178191
val versions = when (val result = provider.getVersionsForMod(id)) {
179192
is VersionResult.Error -> {
180-
logger.error("Error while getting versions for mod {}", metadata.id)
193+
logger.error("Error while getting versions for mod {}", metadata.id, result.cause)
181194
ModManager.modManager.setModState(metadata.id, id, ModState.INSTALLED)
182195
return
183196
}
184197
is VersionResult.Success -> result.versions
185198
}
186-
val version = findLatestCompatible(metadata.version.friendlyString, versions)
199+
val version = VersionFinder.findUpdate(
200+
metadata.version.friendlyString,
201+
ModManager.getMinecraftVersion(),
202+
ModManager.modManager.config.updateChannel,
203+
versions
204+
)
187205
if (version == null) {
188206
logger.info("No update for {} found!", metadata.id)
189207
ModManager.modManager.setModState(metadata.id, id, ModState.INSTALLED)
@@ -212,7 +230,12 @@ class UpdateManager {
212230
is VersionResult.Error -> return ModInstallResult.Error(result.text, result.cause)
213231
is VersionResult.Success -> result.versions
214232
}
215-
val version = findLatestCompatible("0.0.0.0", versions)
233+
val version = VersionFinder.findUpdate(
234+
"0.0.0.0",
235+
ModManager.getMinecraftVersion(),
236+
ModManager.modManager.config.updateChannel,
237+
versions
238+
)
216239
?: return ModInstallResult.Error(TranslatableText("modmanager.error.noCompatibleModVersionFound"))
217240

218241
val dir = FabricLoader.getInstance().gameDir.resolve("mods")
@@ -258,34 +281,6 @@ class UpdateManager {
258281
}
259282
}
260283

261-
private fun findLatestCompatible(installedVersion: String, versions: List<Version>): Version? {
262-
var latest: Version? = null
263-
var latestVersion: SemanticVersion? = null
264-
val installVersion =
265-
VersionDeserializer.deserializeSemantic(installedVersion.split("+")[0]) // Remove additional info from version
266-
for (version in versions) {
267-
if (!version.gameVersions.contains(ModManager.getMinecraftVersion()) ||
268-
!ModManager.modManager.config.isReleaseAllowed(version.type)
269-
) {
270-
continue
271-
}
272-
val ver = try {
273-
VersionDeserializer.deserializeSemantic(version.version.split("+")[0]) // Remove additional info from version
274-
} catch (e: Exception) {
275-
logger.warn("Skipping error producing version {}", version.version)
276-
continue
277-
}
278-
if (latestVersion == null || ver > latestVersion) {
279-
latest = version
280-
latestVersion = ver
281-
}
282-
}
283-
if (latestVersion?.compareTo(installVersion) == 0) {
284-
return null
285-
}
286-
return latest
287-
}
288-
289284
fun updateMod(update: Update): ModUpdateResult {
290285
val oldUpdate = FabricLoader.getInstance().allMods.find { it.metadata.id == update.fabricId }
291286
?: return ModUpdateResult.Error(TranslatableText("modmanager.error.container.notFound"))
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2021 DeathsGun
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package xyz.deathsgun.modmanager.update
18+
19+
import net.fabricmc.loader.api.SemanticVersion
20+
import net.fabricmc.loader.api.VersionParsingException
21+
import net.fabricmc.loader.util.version.VersionDeserializer
22+
import xyz.deathsgun.modmanager.api.mod.Version
23+
import xyz.deathsgun.modmanager.config.Config
24+
25+
object VersionFinder {
26+
27+
fun findUpdateFallback(
28+
installedVersion: String,
29+
mcVersion: String,
30+
updateChannel: Config.UpdateChannel,
31+
modVersions: List<Version>
32+
): Version? {
33+
val versions =
34+
modVersions.filter { updateChannel.isReleaseAllowed(it.type) }
35+
.filter { it.gameVersions.any { it1 -> it1.startsWith(mcVersion) } }
36+
.sortedByDescending { it.releaseDate }
37+
38+
val version = versions.firstOrNull()
39+
if (version?.version == installedVersion) {
40+
return null
41+
}
42+
return version
43+
}
44+
45+
internal fun findUpdateByVersion(
46+
installedVersion: String,
47+
mcVersion: String,
48+
channel: Config.UpdateChannel,
49+
modVersions: List<Version>
50+
): Version? {
51+
val versions = modVersions.filter { channel.isReleaseAllowed(it.type) }
52+
.filter { it.gameVersions.any { it1 -> it1.startsWith(mcVersion) } }
53+
var latestVersion: Version? = null
54+
var latestVer: SemanticVersion? = null
55+
val installedVer = VersionDeserializer.deserializeSemantic(installedVersion)
56+
for (version in versions) {
57+
val parsedVersion = VersionDeserializer.deserializeSemantic(version.version)
58+
if (latestVersion == null) {
59+
latestVersion = version
60+
latestVer = parsedVersion
61+
continue
62+
}
63+
if (latestVer != null && parsedVersion > latestVer) {
64+
latestVersion = version
65+
latestVer = parsedVersion
66+
}
67+
}
68+
if (installedVersion == latestVersion?.version || (latestVer != null && installedVer >= latestVer)) {
69+
return null
70+
}
71+
return latestVersion
72+
}
73+
74+
fun findUpdate(
75+
installedVersion: String,
76+
mcVersion: String,
77+
channel: Config.UpdateChannel,
78+
modVersions: List<Version>
79+
): Version? {
80+
return try {
81+
findUpdateByVersion(installedVersion, mcVersion, channel, modVersions)
82+
} catch (e: VersionParsingException) {
83+
findUpdateFallback(installedVersion, mcVersion, channel, modVersions)
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)