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

Commit c386e38

Browse files
committed
Added ModUpdateTask
- Moved TitleScreenMixin to client - Deactivate previous page button when on page 0
1 parent d5f3e26 commit c386e38

11 files changed

Lines changed: 165 additions & 84 deletions

File tree

src/main/java/xyz/deathsgun/modmanager/ModManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ public static ModState getState(SummarizedMod mod) {
8181
if (getModManipulationManager().isMarkedUninstalled(mod)) {
8282
return ModState.DOWNLOADABLE;
8383
}
84+
if (getModManipulationManager().isMarkedUpdated(mod)) {
85+
return ModState.INSTALLED;
86+
}
8487
return updateCheckService.isUpdateAvailable(mod, installedMod.get().getMetadata()) ? ModState.OUTDATED : ModState.INSTALLED;
8588
}
8689

src/main/java/xyz/deathsgun/modmanager/gui/ModsOverviewScreen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
9090
@Override
9191
public void tick() {
9292
this.searchBox.tick();
93+
this.previousPage.active = this.modListWidget.getCurrentPage() > 0;
9394
this.nextPage.active = this.modListWidget.getEntryCount() >= this.modListWidget.getLimit();
9495
}
9596

src/main/java/xyz/deathsgun/modmanager/gui/widget/ModListWidget.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public void setCategory(Category category, boolean force) {
5252
this.clearMods();
5353
if (category.id().equals("updatable")) {
5454
this.addUpdatableMods();
55+
return;
5556
}
5657
try {
5758
ModManager.getModProvider().getMods(category, page, limit)
@@ -62,8 +63,9 @@ public void setCategory(Category category, boolean force) {
6263
}
6364

6465
private void addUpdatableMods() {
65-
ModManager.getUpdateChecker().getUpdatableMods().forEach(mod ->
66-
this.addEntry(new ModListEntry(this, mod)));
66+
ModManager.getUpdateChecker().getUpdatableMods().stream()
67+
.filter(detailedMod -> !ModManager.getModManipulationManager().isMarkedUpdated(detailedMod.toSummarizedMod()))
68+
.forEach(mod -> this.addEntry(new ModListEntry(this, mod)));
6769
}
6870

6971
public void searchMods(String query) {
@@ -141,6 +143,10 @@ public void showPreviousPage() {
141143
this.searchMods(this.query);
142144
}
143145

146+
public int getCurrentPage() {
147+
return page;
148+
}
149+
144150
public void close() {
145151
ModManager.getIconManager().destroyAllIcons();
146152
}

src/main/java/xyz/deathsgun/modmanager/manager/ModManipulationManager.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616

1717
package xyz.deathsgun.modmanager.manager;
1818

19+
import com.google.gson.JsonArray;
1920
import xyz.deathsgun.modmanager.ModManager;
2021
import xyz.deathsgun.modmanager.api.manipulation.TaskCallback;
2122
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
2223
import xyz.deathsgun.modmanager.tasks.ModDownloadTask;
2324
import xyz.deathsgun.modmanager.tasks.ModRemovalTask;
25+
import xyz.deathsgun.modmanager.tasks.ModUpdateTask;
2426
import xyz.deathsgun.modmanager.util.FabricMods;
2527

2628
import java.util.ArrayList;
@@ -29,6 +31,7 @@ public class ModManipulationManager {
2931

3032
private final ArrayList<String> manuallyInstalled = new ArrayList<>();
3133
private final ArrayList<String> uninstalledMods = new ArrayList<>();
34+
private final ArrayList<String> updatedMods = new ArrayList<>();
3235

3336
public void installMod(SummarizedMod mod, TaskCallback taskCallback) {
3437
ModManager.getManipulationService().add(new ModDownloadTask(mod.id() + "_mod_download", mod, taskCallback));
@@ -39,6 +42,12 @@ public void markManuallyInstalled(SummarizedMod mod) {
3942
this.uninstalledMods.removeIf(s -> mod.id().equals(s));
4043
}
4144

45+
public void markManuallyUpdated(SummarizedMod mod) {
46+
this.updatedMods.add(mod.id());
47+
this.manuallyInstalled.removeIf(s -> mod.id().equals(s));
48+
this.uninstalledMods.removeIf(s -> mod.id().equals(s));
49+
}
50+
4251
public void removeManuallyInstalled(SummarizedMod mod) {
4352
this.manuallyInstalled.removeIf(s -> mod.id().equals(s));
4453
this.uninstalledMods.add(mod.id());
@@ -56,7 +65,11 @@ public boolean isMarkedUninstalled(SummarizedMod summarizedMod) {
5665
return this.uninstalledMods.contains(summarizedMod.id());
5766
}
5867

59-
public void updateMod(SummarizedMod summarizedMod, TaskCallback taskCallback) {
68+
public void updateMod(SummarizedMod mod, TaskCallback taskCallback) {
69+
ModManager.getManipulationService().add(new ModUpdateTask(mod.id() + "_mod_update", mod, taskCallback));
70+
}
6071

72+
public boolean isMarkedUpdated(SummarizedMod mod) {
73+
return this.updatedMods.contains(mod.id());
6174
}
6275
}

src/main/java/xyz/deathsgun/modmanager/services/UpdateCheckService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private void checkForUpdate(ModMetadata metadata) {
7070
}
7171
updates.add(new AvailableUpdates(modId, metadata.getId(), version));
7272
} catch (Exception e) {
73-
logger.error("Failed to check for updates for {}", metadata.getId(), e);
73+
logger.error("Failed to check for updates for {}", metadata.getId());
7474
}
7575
}
7676

src/main/java/xyz/deathsgun/modmanager/tasks/ModDownloadTask.java

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,14 @@
1616

1717
package xyz.deathsgun.modmanager.tasks;
1818

19-
import net.fabricmc.loader.api.FabricLoader;
20-
import net.fabricmc.loader.api.SemanticVersion;
21-
import net.fabricmc.loader.util.version.VersionDeserializer;
22-
import net.minecraft.MinecraftVersion;
2319
import org.apache.logging.log4j.LogManager;
2420
import org.jetbrains.annotations.NotNull;
2521
import org.jetbrains.annotations.Nullable;
2622
import xyz.deathsgun.modmanager.ModManager;
27-
import xyz.deathsgun.modmanager.api.manipulation.TaskCallback;
2823
import xyz.deathsgun.modmanager.api.manipulation.NetworkTask;
29-
import xyz.deathsgun.modmanager.api.mod.Asset;
30-
import xyz.deathsgun.modmanager.api.mod.ModVersion;
24+
import xyz.deathsgun.modmanager.api.manipulation.TaskCallback;
3125
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
32-
import xyz.deathsgun.modmanager.api.provider.IModProvider;
33-
34-
import java.net.URI;
35-
import java.net.http.HttpRequest;
36-
import java.net.http.HttpResponse;
37-
import java.nio.file.Path;
38-
import java.util.List;
39-
import java.util.Optional;
40-
import java.util.stream.Collectors;
26+
import xyz.deathsgun.modmanager.util.InstallationUtil;
4127

4228
public class ModDownloadTask extends NetworkTask {
4329

@@ -51,43 +37,8 @@ protected void execute() throws Exception {
5137
if (subject == null) {
5238
throw new Exception("Summarized mod is empty");
5339
}
54-
downloadMod(getVersionForMod(subject));
40+
InstallationUtil.downloadMod(http, InstallationUtil.getVersionForMod(subject));
5541
ModManager.getModManipulationManager().markManuallyInstalled(subject);
5642
}
5743

58-
private ModVersion getVersionForMod(SummarizedMod mod) throws Exception {
59-
IModProvider provider = ModManager.getModProvider();
60-
List<ModVersion> versions = provider.getVersionsForMod(mod.id()).stream()
61-
.filter(value -> value.gameVersions().contains(MinecraftVersion.GAME_VERSION.getReleaseTarget())).collect(Collectors.toList());
62-
ModVersion latest = null;
63-
SemanticVersion latestVersion = null;
64-
for (ModVersion modVersion : versions) {
65-
if (!modVersion.gameVersions().contains(MinecraftVersion.GAME_VERSION.getReleaseTarget())) {
66-
continue;
67-
}
68-
SemanticVersion version = VersionDeserializer.deserializeSemantic(modVersion.version());
69-
if (latestVersion == null || version.compareTo(latestVersion) > 0) {
70-
latest = modVersion;
71-
latestVersion = version;
72-
}
73-
}
74-
return latest;
75-
}
76-
77-
private void downloadMod(ModVersion version) throws Exception {
78-
if (version == null) {
79-
throw new Exception("no version found!");
80-
}
81-
Optional<Asset> asset = version.assets().stream().filter(value -> value.filename().endsWith(".jar")).findFirst();
82-
if (asset.isEmpty()) {
83-
throw new Exception("jar in downloadable assets found");
84-
}
85-
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create(asset.get().url())).build();
86-
Path output = FabricLoader.getInstance().getGameDir().resolve("mods").resolve(asset.get().filename());
87-
HttpResponse<Path> response = this.http.send(request, HttpResponse.BodyHandlers.ofFile(output));
88-
if (response.statusCode() != 200) {
89-
throw new Exception("Invalid status code: " + response.statusCode());
90-
}
91-
}
92-
9344
}

src/main/java/xyz/deathsgun/modmanager/tasks/ModRemovalTask.java

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,19 @@
1616

1717
package xyz.deathsgun.modmanager.tasks;
1818

19-
import com.google.gson.Gson;
20-
import net.fabricmc.loader.api.FabricLoader;
2119
import net.fabricmc.loader.api.ModContainer;
2220
import org.apache.logging.log4j.LogManager;
2321
import org.jetbrains.annotations.NotNull;
2422
import org.jetbrains.annotations.Nullable;
2523
import xyz.deathsgun.modmanager.ModManager;
26-
import xyz.deathsgun.modmanager.api.manipulation.TaskCallback;
2724
import xyz.deathsgun.modmanager.api.manipulation.ManipulationTask;
25+
import xyz.deathsgun.modmanager.api.manipulation.TaskCallback;
2826
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
29-
import xyz.deathsgun.modmanager.model.ReducedModMetadata;
3027
import xyz.deathsgun.modmanager.util.FabricMods;
3128

32-
import java.io.InputStreamReader;
3329
import java.nio.file.Files;
3430
import java.nio.file.Path;
35-
import java.util.List;
3631
import java.util.Optional;
37-
import java.util.stream.Collectors;
38-
import java.util.zip.ZipEntry;
39-
import java.util.zip.ZipFile;
4032

4133
public class ModRemovalTask extends ManipulationTask {
4234

@@ -57,29 +49,12 @@ protected void execute() throws Exception {
5749
id = subject.slug();
5850
name = subject.name();
5951
}
60-
Path jar = getJarFromModContainer(id, name);
52+
Path jar = FabricMods.getJarFromModContainer(id, name);
6153
if (jar == null) {
6254
throw new Exception(String.format("Couldn't find jar for %s", subject.name()));
6355
}
6456
Files.delete(jar);
6557
ModManager.getModManipulationManager().removeManuallyInstalled(subject);
6658
}
6759

68-
private Path getJarFromModContainer(String id, String name) throws Exception {
69-
List<Path> jars = Files.list(FabricLoader.getInstance().getGameDir().resolve("mods"))
70-
.filter(file -> file.toFile().getName().endsWith(".jar"))
71-
.collect(Collectors.toList());
72-
Gson gson = new Gson();
73-
for (Path path : jars) {
74-
ZipFile zipFile = new ZipFile(path.toFile());
75-
ZipEntry entry = zipFile.getEntry("fabric.mod.json");
76-
ReducedModMetadata metadata = gson.fromJson(new InputStreamReader(zipFile.getInputStream(entry)), ReducedModMetadata.class);
77-
zipFile.close();
78-
if (metadata.getId().equals(id) || metadata.getName().equals(name)) {
79-
return path;
80-
}
81-
}
82-
return null;
83-
}
84-
8560
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package xyz.deathsgun.modmanager.tasks;
2+
3+
import net.fabricmc.loader.api.ModContainer;
4+
import org.apache.logging.log4j.LogManager;
5+
import xyz.deathsgun.modmanager.ModManager;
6+
import xyz.deathsgun.modmanager.api.manipulation.NetworkTask;
7+
import xyz.deathsgun.modmanager.api.manipulation.TaskCallback;
8+
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
9+
import xyz.deathsgun.modmanager.util.FabricMods;
10+
import xyz.deathsgun.modmanager.util.InstallationUtil;
11+
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.util.Optional;
15+
16+
public class ModUpdateTask extends NetworkTask {
17+
18+
public ModUpdateTask(String taskId, SummarizedMod mod, TaskCallback taskCallback) {
19+
super(taskId, mod, taskCallback);
20+
logger = LogManager.getLogger("Mod remover");
21+
}
22+
23+
@SuppressWarnings("DuplicatedCode")
24+
@Override
25+
protected void execute() throws Exception {
26+
if (subject == null) {
27+
throw new Exception("Summarized mod is empty");
28+
}
29+
Optional<ModContainer> container = FabricMods.getModContainerByMod(subject);
30+
String id, name;
31+
if (container.isPresent()) {
32+
id = container.get().getMetadata().getId();
33+
name = container.get().getMetadata().getName();
34+
} else {
35+
debug("Getting mod id from summarized mod (this may fail)");
36+
id = subject.slug();
37+
name = subject.name();
38+
}
39+
Path jar = FabricMods.getJarFromModContainer(id, name);
40+
if (jar == null) {
41+
throw new Exception(String.format("Couldn't find jar for %s", subject.name()));
42+
}
43+
Files.delete(jar);
44+
InstallationUtil.downloadMod(http, InstallationUtil.getVersionForMod(subject));
45+
ModManager.getModManipulationManager().markManuallyUpdated(subject);
46+
}
47+
}

src/main/java/xyz/deathsgun/modmanager/util/FabricMods.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,20 @@
1616

1717
package xyz.deathsgun.modmanager.util;
1818

19+
import com.google.gson.Gson;
1920
import net.fabricmc.loader.api.FabricLoader;
2021
import net.fabricmc.loader.api.ModContainer;
2122
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
23+
import xyz.deathsgun.modmanager.model.ReducedModMetadata;
2224

25+
import java.io.InputStreamReader;
26+
import java.nio.file.Files;
27+
import java.nio.file.Path;
28+
import java.util.List;
2329
import java.util.Optional;
30+
import java.util.stream.Collectors;
31+
import java.util.zip.ZipEntry;
32+
import java.util.zip.ZipFile;
2433

2534
public class FabricMods {
2635

@@ -30,4 +39,21 @@ public static Optional<ModContainer> getModContainerByMod(SummarizedMod mod) {
3039
metadata.getMetadata().getName().equalsIgnoreCase(mod.name())).findFirst();
3140
}
3241

42+
public static Path getJarFromModContainer(String id, String name) throws Exception {
43+
List<Path> jars = Files.list(FabricLoader.getInstance().getGameDir().resolve("mods"))
44+
.filter(file -> file.toFile().getName().endsWith(".jar"))
45+
.collect(Collectors.toList());
46+
Gson gson = new Gson();
47+
for (Path path : jars) {
48+
ZipFile zipFile = new ZipFile(path.toFile());
49+
ZipEntry entry = zipFile.getEntry("fabric.mod.json");
50+
ReducedModMetadata metadata = gson.fromJson(new InputStreamReader(zipFile.getInputStream(entry)), ReducedModMetadata.class);
51+
zipFile.close();
52+
if (metadata.getId().equals(id) || metadata.getName().equals(name)) {
53+
return path;
54+
}
55+
}
56+
return null;
57+
}
58+
3359
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package xyz.deathsgun.modmanager.util;
2+
3+
import net.fabricmc.loader.api.FabricLoader;
4+
import net.fabricmc.loader.api.SemanticVersion;
5+
import net.fabricmc.loader.util.version.VersionDeserializer;
6+
import net.minecraft.MinecraftVersion;
7+
import xyz.deathsgun.modmanager.ModManager;
8+
import xyz.deathsgun.modmanager.api.mod.Asset;
9+
import xyz.deathsgun.modmanager.api.mod.ModVersion;
10+
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
11+
import xyz.deathsgun.modmanager.api.provider.IModProvider;
12+
13+
import java.net.URI;
14+
import java.net.http.HttpClient;
15+
import java.net.http.HttpRequest;
16+
import java.net.http.HttpResponse;
17+
import java.nio.file.Path;
18+
import java.util.List;
19+
import java.util.Optional;
20+
import java.util.stream.Collectors;
21+
22+
public class InstallationUtil {
23+
24+
public static ModVersion getVersionForMod(SummarizedMod mod) throws Exception {
25+
IModProvider provider = ModManager.getModProvider();
26+
List<ModVersion> versions = provider.getVersionsForMod(mod.id()).stream()
27+
.filter(value -> value.gameVersions().contains(MinecraftVersion.GAME_VERSION.getReleaseTarget())).collect(Collectors.toList());
28+
ModVersion latest = null;
29+
SemanticVersion latestVersion = null;
30+
for (ModVersion modVersion : versions) {
31+
if (!modVersion.gameVersions().contains(MinecraftVersion.GAME_VERSION.getReleaseTarget())) {
32+
continue;
33+
}
34+
SemanticVersion version = VersionDeserializer.deserializeSemantic(modVersion.version());
35+
if (latestVersion == null || version.compareTo(latestVersion) > 0) {
36+
latest = modVersion;
37+
latestVersion = version;
38+
}
39+
}
40+
return latest;
41+
}
42+
43+
public static void downloadMod(HttpClient http, ModVersion version) throws Exception {
44+
if (version == null) {
45+
throw new Exception("no version found!");
46+
}
47+
Optional<Asset> asset = version.assets().stream().filter(value -> value.filename().endsWith(".jar")).findFirst();
48+
if (asset.isEmpty()) {
49+
throw new Exception("jar in downloadable assets found");
50+
}
51+
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create(asset.get().url())).build();
52+
Path output = FabricLoader.getInstance().getGameDir().resolve("mods").resolve(asset.get().filename());
53+
HttpResponse<Path> response = http.send(request, HttpResponse.BodyHandlers.ofFile(output));
54+
if (response.statusCode() != 200) {
55+
throw new Exception("Invalid status code: " + response.statusCode());
56+
}
57+
}
58+
59+
}

0 commit comments

Comments
 (0)