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

Commit f08d6c5

Browse files
authored
Merge pull request #93 from DeathsGun/bugs/91_delete_mods_prelaunch
Delete mods on next start using preLaunch hook
2 parents 473371a + 6e023fa commit f08d6c5

File tree

4 files changed

+97
-33
lines changed

4 files changed

+97
-33
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ class ModManager : ClientModInitializer {
6868
provider[modrinth.getName().lowercase()] = modrinth
6969
updateProvider[modrinth.getName().lowercase()] = modrinth
7070
GlobalScope.launch {
71-
update.fullyDeleteMods()
7271
update.checkUpdates()
7372
icons.cleanupCache()
7473
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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
18+
19+
import kotlinx.serialization.ExperimentalSerializationApi
20+
import kotlinx.serialization.decodeFromString
21+
import kotlinx.serialization.json.Json
22+
import net.fabricmc.loader.api.FabricLoader
23+
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint
24+
import org.apache.logging.log4j.LogManager
25+
import java.nio.file.Files
26+
import kotlin.io.path.Path
27+
import kotlin.io.path.deleteIfExists
28+
29+
class PreLaunchHook : PreLaunchEntrypoint {
30+
31+
private val logger = LogManager.getLogger("ModManager")
32+
33+
override fun onPreLaunch() {
34+
val filesToDelete = try {
35+
loadFiles()
36+
} catch (e: Exception) {
37+
ArrayList()
38+
}
39+
for (file in filesToDelete) {
40+
logger.info("Deleting {}", file)
41+
val path = Path(file)
42+
Files.delete(path)
43+
}
44+
}
45+
46+
@OptIn(ExperimentalSerializationApi::class)
47+
private fun loadFiles(): ArrayList<String> {
48+
val configFile = FabricLoader.getInstance().configDir.resolve(".modmanager.delete.json")
49+
if (Files.notExists(configFile)) {
50+
return ArrayList()
51+
}
52+
val data = Files.readString(configFile, Charsets.UTF_8)
53+
configFile.deleteIfExists()
54+
return Json.decodeFromString(data)
55+
}
56+
57+
}

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

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import kotlinx.coroutines.coroutineScope
2121
import kotlinx.coroutines.launch
2222
import kotlinx.serialization.ExperimentalSerializationApi
2323
import kotlinx.serialization.decodeFromString
24+
import kotlinx.serialization.encodeToString
2425
import kotlinx.serialization.json.Json
2526
import net.fabricmc.loader.api.FabricLoader
2627
import net.fabricmc.loader.api.metadata.ModMetadata
@@ -40,14 +41,14 @@ import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider
4041
import xyz.deathsgun.modmanager.api.provider.Sorting
4142
import xyz.deathsgun.modmanager.models.FabricMetadata
4243
import xyz.deathsgun.modmanager.state.ModState
44+
import java.io.File
4345
import java.math.BigInteger
4446
import java.net.URI
4547
import java.net.http.HttpClient
4648
import java.net.http.HttpRequest
4749
import java.net.http.HttpResponse
4850
import java.nio.file.Files
4951
import java.nio.file.Path
50-
import java.nio.file.StandardOpenOption
5152
import java.security.MessageDigest
5253
import java.time.Duration
5354
import java.util.zip.ZipFile
@@ -59,8 +60,13 @@ class UpdateManager {
5960
private val logger = LogManager.getLogger("UpdateCheck")
6061
private val blockedIds = arrayOf("java", "minecraft", "fabricloader")
6162
private val http: HttpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(15)).build()
63+
private val deletableMods = ArrayList<String>()
6264
val updates = ArrayList<Update>()
6365

66+
init {
67+
Runtime.getRuntime().addShutdownHook(Thread(this::saveDeletableFiles))
68+
}
69+
6470
//region Update Checking
6571

6672
suspend fun checkUpdates() = coroutineScope {
@@ -320,11 +326,7 @@ class UpdateManager {
320326
FileUtils.listFiles(FabricLoader.getInstance().gameDir.resolve("mods").toFile(), arrayOf("jar"), true)
321327
return try {
322328
for (jar in jars) {
323-
val jarFile = ZipFile(jar)
324-
val fabricEntry = jarFile.getEntry("fabric.mod.json")
325-
val data = jarFile.getInputStream(fabricEntry).bufferedReader().use { it.readText() }
326-
val meta = json.decodeFromString<FabricMetadata>(data)
327-
jarFile.close()
329+
val meta = openFabricMeta(jar)
328330
if (meta.id == container.id) {
329331
return jar.toPath()
330332
}
@@ -335,17 +337,12 @@ class UpdateManager {
335337
}
336338
}
337339

338-
@OptIn(ExperimentalSerializationApi::class)
339-
fun findJarByMod(mod: Mod): Path? {
340+
private fun findJarByMod(mod: Mod): Path? {
340341
val jars =
341342
FileUtils.listFiles(FabricLoader.getInstance().gameDir.resolve("mods").toFile(), arrayOf("jar"), true)
342343
return try {
343344
for (jar in jars) {
344-
val jarFile = ZipFile(jar)
345-
val fabricEntry = jarFile.getEntry("fabric.mod.json")
346-
val data = jarFile.getInputStream(fabricEntry).bufferedReader().use { it.readText() }
347-
val meta = json.decodeFromString<FabricMetadata>(data)
348-
jarFile.close()
345+
val meta = openFabricMeta(jar)
349346
if (meta.id == mod.id || meta.id == mod.slug || meta.id == mod.slug.replace("-", "") ||
350347
meta.custom.modmanager[ModManager.modManager.config.defaultProvider] == mod.id ||
351348
meta.id.replace("_", "-") == mod.id ||
@@ -360,6 +357,16 @@ class UpdateManager {
360357
}
361358
}
362359

360+
@OptIn(ExperimentalSerializationApi::class)
361+
private fun openFabricMeta(file: File): FabricMetadata {
362+
val jarFile = ZipFile(file)
363+
val fabricEntry = jarFile.getEntry("fabric.mod.json")
364+
val data = jarFile.getInputStream(fabricEntry).bufferedReader().use { it.readText() }
365+
val meta = json.decodeFromString<FabricMetadata>(data)
366+
jarFile.close()
367+
return meta
368+
}
369+
363370
private fun getIdBy(metadata: ModMetadata): Map<String, String>? {
364371
if (!metadata.containsCustomValue("modmanager")) {
365372
return null
@@ -372,6 +379,18 @@ class UpdateManager {
372379
return ids
373380
}
374381

382+
@OptIn(ExperimentalSerializationApi::class)
383+
private fun saveDeletableFiles() {
384+
if (deletableMods.isEmpty()) {
385+
return
386+
}
387+
logger.info("Deleting {} mods on the next start", deletableMods.size)
388+
val configFile = FabricLoader.getInstance().configDir.resolve(".modmanager.delete.json")
389+
val data = json.encodeToString(deletableMods)
390+
Files.writeString(configFile, data, Charsets.UTF_8)
391+
}
392+
393+
375394
private fun getCheckableMods(): List<ModMetadata> {
376395
return FabricLoader.getInstance().allMods.map { it.metadata }.filter {
377396
!it.id.startsWith("fabric-") &&
@@ -394,7 +413,7 @@ class UpdateManager {
394413
Files.delete(this)
395414
} catch (e: Exception) {
396415
logger.info("Error while deleting {} trying on restart again", this.absolutePathString())
397-
Files.writeString(this, "MODMANAGER", StandardOpenOption.WRITE)
416+
deletableMods.add(this.absolutePathString())
398417
}
399418
}
400419

@@ -425,21 +444,4 @@ class UpdateManager {
425444
return URI("dummy", url.replace("\t", ""), null).rawSchemeSpecificPart
426445
}
427446

428-
fun fullyDeleteMods() {
429-
val jars =
430-
FileUtils.listFiles(FabricLoader.getInstance().gameDir.resolve("mods").toFile(), arrayOf("jar"), true)
431-
for (jar in jars) {
432-
val content = try {
433-
Files.readString(jar.toPath())
434-
} catch (e: Exception) {
435-
""
436-
}
437-
if (content != "MODMANGER") {
438-
continue
439-
}
440-
logger.info("Deleting {}", jar.absolutePath)
441-
jar.delete()
442-
}
443-
}
444-
445447
}

src/main/resources/fabric.mod.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,15 @@
2222
"value": "xyz.deathsgun.modmanager.ModManager"
2323
}
2424
],
25+
"preLaunch": [
26+
{
27+
"adapter": "kotlin",
28+
"value": "xyz.deathsgun.modmanager.PreLaunchHook"
29+
}
30+
],
2531
"modmenu": [
2632
"xyz.deathsgun.modmanager.ModMenuEntrypoint"
27-
]
33+
]
2834
},
2935
"custom": {
3036
"modmanager": {

0 commit comments

Comments
 (0)