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

Commit 793d2dd

Browse files
committed
Reworked service structure to task based structure
TODO: Rewrite UpdateCheckService to UpdateCheckTask and UpdateModTask TODO: Correctly implement them into the GUI TODO: Better meaningful error messages TODO: Handle dependencies of mods TODO: Update all button TODO: Updatable mods overview Signed-off-by: DeathsGun <deathsgun@protonmail.com>
1 parent 561b5d2 commit 793d2dd

25 files changed

Lines changed: 602 additions & 252 deletions

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#
1616

1717
# Done to increase the memory available to gradle.
18-
org.gradle.jvmargs=-Xmx4G
18+
org.gradle.jvmargs=-Xms2G -Xmx4G
1919
# Fabric Properties
2020
# check this on https://modmuss50.me/fabric.html
2121
minecraft_version=1.17

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

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,16 @@
2020
import net.fabricmc.api.ClientModInitializer;
2121
import net.fabricmc.api.EnvType;
2222
import net.fabricmc.api.Environment;
23-
import net.fabricmc.loader.api.FabricLoader;
2423
import net.fabricmc.loader.api.ModContainer;
2524
import xyz.deathsgun.modmanager.api.mod.ModState;
2625
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
2726
import xyz.deathsgun.modmanager.api.provider.IModProvider;
27+
import xyz.deathsgun.modmanager.manager.IconManager;
28+
import xyz.deathsgun.modmanager.manager.ModManipulationManager;
2829
import xyz.deathsgun.modmanager.providers.modrinth.Modrinth;
29-
import xyz.deathsgun.modmanager.services.IconDownloadService;
30-
import xyz.deathsgun.modmanager.services.ModDownloadService;
30+
import xyz.deathsgun.modmanager.services.ManipulationService;
3131
import xyz.deathsgun.modmanager.services.UpdateCheckService;
32+
import xyz.deathsgun.modmanager.util.FabricMods;
3233

3334
import java.util.ArrayList;
3435
import java.util.Optional;
@@ -38,9 +39,10 @@ public class ModManager implements ClientModInitializer, ModMenuApi {
3839

3940
private static final String currentProvider = "Modrinth";
4041
private static final ArrayList<IModProvider> modProviders = new ArrayList<>();
42+
private static final ManipulationService manipulationService = new ManipulationService();
43+
private static final IconManager iconManager = new IconManager();
44+
private static final ModManipulationManager modManipulationManager = new ModManipulationManager();
4145
private static final UpdateCheckService updateCheckService = new UpdateCheckService();
42-
private static final ModDownloadService modDownloadService = new ModDownloadService();
43-
private static final IconDownloadService iconService = new IconDownloadService();
4446

4547
public static void registerModProvider(IModProvider provider) {
4648
ModManager.modProviders.removeIf(value -> value.getName().equals(provider.getName()));
@@ -51,32 +53,35 @@ public static IModProvider getModProvider() {
5153
return modProviders.stream().filter(iModProvider -> iModProvider.getName().equals(currentProvider)).findFirst().orElse(null);
5254
}
5355

54-
public static IconDownloadService getIconDownloader() {
55-
return iconService;
56+
public static IconManager getIconManager() {
57+
return iconManager;
5658
}
5759

58-
public static ModDownloadService getModDownloader() {
59-
return modDownloadService;
60+
public static ModManipulationManager getModManipulationManager() {
61+
return modManipulationManager;
6062
}
6163

6264
public static UpdateCheckService getUpdateChecker() {
6365
return updateCheckService;
6466
}
6567

66-
@Override
67-
public void onInitializeClient() {
68-
registerModProvider(new Modrinth());
68+
public static ManipulationService getManipulationService() {
69+
return manipulationService;
70+
}
71+
72+
public static String getVersion() {
73+
return "0.1.0";
6974
}
7075

7176
public static ModState getState(SummarizedMod mod) {
72-
Optional<ModContainer> installedMod = getInstalledMod(mod);
73-
return installedMod.map(modContainer -> updateCheckService.isUpdateAvailable(mod, modContainer) ? ModState.OUTDATED : ModState.INSTALLED).orElse(ModState.DOWNLOADABLE);
77+
Optional<ModContainer> installedMod = FabricMods.getModContainerByMod(mod);
78+
return installedMod.map(modContainer -> updateCheckService.isUpdateAvailable(mod, modContainer.getMetadata()) ? ModState.OUTDATED : ModState.INSTALLED).orElse(ModState.DOWNLOADABLE);
7479
}
7580

76-
private static Optional<ModContainer> getInstalledMod(SummarizedMod mod) {
77-
return FabricLoader.getInstance().getAllMods().stream().filter(container -> container.getMetadata().getId().equalsIgnoreCase(mod.slug()) ||
78-
container.getMetadata().getId().equalsIgnoreCase(mod.slug().replaceAll("-", "")))
79-
.filter(container -> container.getMetadata().getAuthors().stream().anyMatch(person -> person.getName().equalsIgnoreCase(mod.author()))).findFirst();
81+
@Override
82+
public void onInitializeClient() {
83+
registerModProvider(new Modrinth());
84+
updateCheckService.start();
8085
}
8186

8287
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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.api.manipulation;
18+
19+
public interface ErrorHandler {
20+
21+
void onError(Exception error);
22+
23+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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.api.manipulation;
18+
19+
import net.fabricmc.loader.api.FabricLoader;
20+
import org.apache.logging.log4j.Logger;
21+
import org.jetbrains.annotations.NotNull;
22+
import org.jetbrains.annotations.Nullable;
23+
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
24+
25+
public abstract class ManipulationTask {
26+
27+
protected final String id;
28+
protected final SummarizedMod subject;
29+
private final @Nullable ErrorHandler errorHandler;
30+
private final boolean debugMode;
31+
protected Logger logger;
32+
protected TaskState state = TaskState.SCHEDULED;
33+
34+
public ManipulationTask(@NotNull String id, @NotNull SummarizedMod subject, @Nullable ErrorHandler errorHandler) {
35+
this.id = id;
36+
this.subject = subject;
37+
this.errorHandler = errorHandler;
38+
this.debugMode = FabricLoader.getInstance().isDevelopmentEnvironment();
39+
}
40+
41+
protected abstract void execute() throws Exception;
42+
43+
public final void executeTask() {
44+
try {
45+
this.state = TaskState.RUNNING;
46+
execute();
47+
this.state = TaskState.FINISHED;
48+
} catch (Exception e) {
49+
e.printStackTrace();
50+
this.state = TaskState.FAILED;
51+
if (errorHandler != null) {
52+
errorHandler.onError(e);
53+
}
54+
}
55+
}
56+
57+
public String getId() {
58+
return id;
59+
}
60+
61+
public TaskState getState() {
62+
return state;
63+
}
64+
65+
public SummarizedMod getSubject() {
66+
return subject;
67+
}
68+
69+
public void debug(String message, Object... o) {
70+
if (!debugMode) {
71+
return;
72+
}
73+
logger.info(message, o);
74+
}
75+
76+
public enum TaskState {
77+
SCHEDULED, RUNNING, FINISHED, FAILED
78+
}
79+
80+
81+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.api.manipulation;
18+
19+
import org.jetbrains.annotations.NotNull;
20+
import org.jetbrains.annotations.Nullable;
21+
import xyz.deathsgun.modmanager.ModManager;
22+
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
23+
24+
import java.net.http.HttpClient;
25+
import java.net.http.HttpRequest;
26+
27+
public abstract class NetworkTask extends ManipulationTask {
28+
29+
protected final HttpClient http;
30+
31+
public NetworkTask(@NotNull String id, @NotNull SummarizedMod subject, @Nullable ErrorHandler errorHandler) {
32+
super(id, subject, errorHandler);
33+
this.http = HttpClient.newHttpClient();
34+
}
35+
36+
public HttpRequest build(HttpRequest.Builder builder) {
37+
return builder.setHeader("User-Agent", "ModManager " + ModManager.getVersion()).build();
38+
}
39+
40+
}

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.mojang.blaze3d.systems.RenderSystem;
2020
import com.terraformersmc.modmenu.util.DrawingUtil;
21+
import net.minecraft.client.MinecraftClient;
2122
import net.minecraft.client.font.TextRenderer;
2223
import net.minecraft.client.gui.DrawableHelper;
2324
import net.minecraft.client.gui.screen.Screen;
@@ -46,6 +47,7 @@ public class ModDetailScreen extends Screen {
4647
private ButtonWidget actionButton;
4748
private DetailedMod detailedMod;
4849
private DescriptionWidget descriptionWidget;
50+
private Exception exception;
4951

5052
public ModDetailScreen(Screen previousScreen, SummarizedMod mod) {
5153
super(new LiteralText(mod.name()));
@@ -78,20 +80,30 @@ protected void init() {
7880
}
7981

8082
private void handleActionClick(ButtonWidget buttonWidget) {
83+
if (exception != null) {
84+
MinecraftClient.getInstance().openScreen(new ModManagerErrorScreen(this, exception));
85+
return;
86+
}
8187
buttonWidget.active = false;
8288
buttonWidget.setMessage(new TranslatableText("modmanager.message.installing"));
83-
ModManager.getModDownloader().addToQueue(detailedMod);
89+
ModManager.getModManipulationManager().installMod(summarizedMod, this::handleErrors);
90+
}
91+
92+
private void handleErrors(Exception e) {
93+
this.exception = e;
94+
ModManager.getManipulationService().removeTasks(summarizedMod.id());
8495
}
8596

8697
@Override
8798
public void tick() {
8899
super.tick();
89-
if (ModManager.getModDownloader().isQueued(detailedMod)) {
90-
actionButton.setMessage(new TranslatableText("modmanager.message.installing"));
100+
if (ModManager.getModManipulationManager().isInstalled(summarizedMod)) {
101+
actionButton.setMessage(new TranslatableText("modmanager.message.remove"));
102+
actionButton.active = true;
91103
return;
92104
}
93-
if (ModManager.getModDownloader().isInstalled(detailedMod)) {
94-
actionButton.setMessage(new TranslatableText("modmanager.message.remove"));
105+
if (exception != null) {
106+
actionButton.setMessage(new TranslatableText("modmanager.message.showError"));
95107
actionButton.active = true;
96108
return;
97109
}
@@ -135,16 +147,16 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
135147
}
136148

137149
private void bindIconTexture() {
138-
if (ModManager.getIconDownloader().isErrored(summarizedMod.id())) {
150+
if (ModManager.getIconManager().isErrored(summarizedMod.id())) {
139151
RenderSystem.setShaderTexture(0, UNKNOWN_ICON);
140152
return;
141153
}
142-
Identifier icon = ModManager.getIconDownloader().getIcon(summarizedMod.id());
154+
Identifier icon = ModManager.getIconManager().getIconByModId(summarizedMod.id());
143155
if (icon == null) {
144-
if (ModManager.getIconDownloader().isLoading(summarizedMod.id())) {
156+
if (ModManager.getIconManager().isLoading(summarizedMod.id())) {
145157
icon = LOADING_ICON;
146158
} else {
147-
ModManager.getIconDownloader().addMod(summarizedMod);
159+
ModManager.getIconManager().downloadIcon(summarizedMod);
148160
return;
149161
}
150162
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ public ModManagerErrorScreen(Screen screen, Exception exception) {
4242
protected void init() {
4343
super.init();
4444
String error = ExceptionUtils.getStackTrace(exception);
45-
error = error.replaceAll("\t", "");
46-
descriptionWidget = this.addSelectableChild(new DescriptionWidget(client, (int) (width * 0.8), height, (int) (height * 0.2), this.height - 36, 9, error));
47-
descriptionWidget.setLeftPos((int) (this.width * 0.1));
45+
error = error.replaceAll("\t", "").replaceAll("\r", "");
46+
descriptionWidget = this.addSelectableChild(new DescriptionWidget(client, (int) (width * 0.90), height, (int) (height * 0.1), this.height - 36, 9, error));
47+
descriptionWidget.setLeftPos((int) (this.width * 0.05));
4848
this.addDrawableChild(new ButtonWidget(this.width / 2 - 154, this.height - 28, 150, 20, ScreenTexts.CANCEL, button -> this.onClose()));
4949
}
5050

@@ -56,7 +56,7 @@ public void onClose() {
5656
@Override
5757
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
5858
renderBackground(matrices);
59-
super.render(matrices, mouseX, mouseY, delta);
6059
this.descriptionWidget.render(matrices, mouseX, mouseY, delta);
60+
super.render(matrices, mouseX, mouseY, delta);
6161
}
6262
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private void init() {
4141
MutableText[] lines = MarkdownPreprocessor.processText(text);
4242
TextRenderer textRenderer = client.textRenderer;
4343
for (MutableText line : lines) {
44-
if (textRenderer.getWidth(line) - 10 >= width) {
44+
if (textRenderer.getWidth(line) >= width - 10) {
4545
List<OrderedText> texts = textRenderer.wrapLines(line, width - 10);
4646
for (OrderedText wrappedLine : texts) {
4747
addEntry(new DescriptionListEntry(this, wrappedLine));

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,16 @@ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth
9696

9797

9898
private void bindIconTexture() {
99-
if (ModManager.getIconDownloader().isErrored(mod.id())) {
99+
if (ModManager.getIconManager().isErrored(mod.id())) {
100100
RenderSystem.setShaderTexture(0, UNKNOWN_ICON);
101101
return;
102102
}
103-
Identifier icon = ModManager.getIconDownloader().getIcon(mod.id());
103+
Identifier icon = ModManager.getIconManager().getIconByModId(mod.id());
104104
if (icon == null) {
105-
if (ModManager.getIconDownloader().isLoading(mod.id())) {
105+
if (ModManager.getIconManager().isLoading(mod.id())) {
106106
icon = LOADING_ICON;
107107
} else {
108-
ModManager.getIconDownloader().addMod(mod);
108+
ModManager.getIconManager().downloadIcon(mod);
109109
return;
110110
}
111111
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@
2222
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
2323
import xyz.deathsgun.modmanager.gui.ModsOverviewScreen;
2424
import xyz.deathsgun.modmanager.gui.widget.better.BetterListWidget;
25-
import xyz.deathsgun.modmanager.services.IconDownloadService;
2625

2726
import java.util.ArrayList;
2827
import java.util.Objects;
2928

3029
public class ModListWidget extends BetterListWidget<ModListEntry> {
3130

3231
private final int limit = 20;
33-
private final IconDownloadService iconDownloadService = new IconDownloadService();
3432
private final ArrayList<SummarizedMod> mods = new ArrayList<>();
3533
private int page = 0;
3634
private Category category;
@@ -103,6 +101,6 @@ public void showPreviousPage() {
103101
}
104102

105103
public void close() {
106-
this.iconDownloadService.destroyIcons();
104+
ModManager.getIconManager().destroyAllIcons();
107105
}
108106
}

0 commit comments

Comments
 (0)