@@ -21,6 +21,7 @@ import kotlinx.coroutines.coroutineScope
21
21
import kotlinx.coroutines.launch
22
22
import kotlinx.serialization.ExperimentalSerializationApi
23
23
import kotlinx.serialization.decodeFromString
24
+ import kotlinx.serialization.encodeToString
24
25
import kotlinx.serialization.json.Json
25
26
import net.fabricmc.loader.api.FabricLoader
26
27
import net.fabricmc.loader.api.metadata.ModMetadata
@@ -40,14 +41,14 @@ import xyz.deathsgun.modmanager.api.provider.IModUpdateProvider
40
41
import xyz.deathsgun.modmanager.api.provider.Sorting
41
42
import xyz.deathsgun.modmanager.models.FabricMetadata
42
43
import xyz.deathsgun.modmanager.state.ModState
44
+ import java.io.File
43
45
import java.math.BigInteger
44
46
import java.net.URI
45
47
import java.net.http.HttpClient
46
48
import java.net.http.HttpRequest
47
49
import java.net.http.HttpResponse
48
50
import java.nio.file.Files
49
51
import java.nio.file.Path
50
- import java.nio.file.StandardOpenOption
51
52
import java.security.MessageDigest
52
53
import java.time.Duration
53
54
import java.util.zip.ZipFile
@@ -59,8 +60,13 @@ class UpdateManager {
59
60
private val logger = LogManager .getLogger(" UpdateCheck" )
60
61
private val blockedIds = arrayOf(" java" , " minecraft" , " fabricloader" )
61
62
private val http: HttpClient = HttpClient .newBuilder().connectTimeout(Duration .ofSeconds(15 )).build()
63
+ private val deletableMods = ArrayList <String >()
62
64
val updates = ArrayList <Update >()
63
65
66
+ init {
67
+ Runtime .getRuntime().addShutdownHook(Thread (this ::saveDeletableFiles))
68
+ }
69
+
64
70
// region Update Checking
65
71
66
72
suspend fun checkUpdates () = coroutineScope {
@@ -320,11 +326,7 @@ class UpdateManager {
320
326
FileUtils .listFiles(FabricLoader .getInstance().gameDir.resolve(" mods" ).toFile(), arrayOf(" jar" ), true )
321
327
return try {
322
328
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)
328
330
if (meta.id == container.id) {
329
331
return jar.toPath()
330
332
}
@@ -335,17 +337,12 @@ class UpdateManager {
335
337
}
336
338
}
337
339
338
- @OptIn(ExperimentalSerializationApi ::class )
339
- fun findJarByMod (mod : Mod ): Path ? {
340
+ private fun findJarByMod (mod : Mod ): Path ? {
340
341
val jars =
341
342
FileUtils .listFiles(FabricLoader .getInstance().gameDir.resolve(" mods" ).toFile(), arrayOf(" jar" ), true )
342
343
return try {
343
344
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)
349
346
if (meta.id == mod.id || meta.id == mod.slug || meta.id == mod.slug.replace(" -" , " " ) ||
350
347
meta.custom.modmanager[ModManager .modManager.config.defaultProvider] == mod.id ||
351
348
meta.id.replace(" _" , " -" ) == mod.id ||
@@ -360,6 +357,16 @@ class UpdateManager {
360
357
}
361
358
}
362
359
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
+
363
370
private fun getIdBy (metadata : ModMetadata ): Map <String , String >? {
364
371
if (! metadata.containsCustomValue(" modmanager" )) {
365
372
return null
@@ -372,6 +379,18 @@ class UpdateManager {
372
379
return ids
373
380
}
374
381
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
+
375
394
private fun getCheckableMods (): List <ModMetadata > {
376
395
return FabricLoader .getInstance().allMods.map { it.metadata }.filter {
377
396
! it.id.startsWith(" fabric-" ) &&
@@ -394,7 +413,7 @@ class UpdateManager {
394
413
Files .delete(this )
395
414
} catch (e: Exception ) {
396
415
logger.info(" Error while deleting {} trying on restart again" , this .absolutePathString())
397
- Files .writeString (this , " MODMANAGER " , StandardOpenOption . WRITE )
416
+ deletableMods.add (this .absolutePathString() )
398
417
}
399
418
}
400
419
@@ -425,21 +444,4 @@ class UpdateManager {
425
444
return URI (" dummy" , url.replace(" \t " , " " ), null ).rawSchemeSpecificPart
426
445
}
427
446
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
-
445
447
}
0 commit comments