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

Commit 561b5d2

Browse files
committed
Improved update process
TODO: Remove all mods which are not a jar Signed-off-by: DeathsGun <deathsgun@protonmail.com>
1 parent 00bb027 commit 561b5d2

13 files changed

Lines changed: 331 additions & 39 deletions

File tree

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

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,27 @@
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;
24+
import net.fabricmc.loader.api.ModContainer;
25+
import xyz.deathsgun.modmanager.api.mod.ModState;
26+
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
2327
import xyz.deathsgun.modmanager.api.provider.IModProvider;
24-
import xyz.deathsgun.modmanager.downloader.IconDownloader;
25-
import xyz.deathsgun.modmanager.downloader.ModDownloader;
2628
import xyz.deathsgun.modmanager.providers.modrinth.Modrinth;
29+
import xyz.deathsgun.modmanager.services.IconDownloadService;
30+
import xyz.deathsgun.modmanager.services.ModDownloadService;
31+
import xyz.deathsgun.modmanager.services.UpdateCheckService;
2732

2833
import java.util.ArrayList;
34+
import java.util.Optional;
2935

3036
@Environment(EnvType.CLIENT)
3137
public class ModManager implements ClientModInitializer, ModMenuApi {
3238

3339
private static final String currentProvider = "Modrinth";
3440
private static final ArrayList<IModProvider> modProviders = new ArrayList<>();
35-
private static final ModDownloader modDownloader = new ModDownloader();
36-
private static final IconDownloader iconDownloader = new IconDownloader();
41+
private static final UpdateCheckService updateCheckService = new UpdateCheckService();
42+
private static final ModDownloadService modDownloadService = new ModDownloadService();
43+
private static final IconDownloadService iconService = new IconDownloadService();
3744

3845
public static void registerModProvider(IModProvider provider) {
3946
ModManager.modProviders.removeIf(value -> value.getName().equals(provider.getName()));
@@ -44,16 +51,32 @@ public static IModProvider getModProvider() {
4451
return modProviders.stream().filter(iModProvider -> iModProvider.getName().equals(currentProvider)).findFirst().orElse(null);
4552
}
4653

47-
public static IconDownloader getIconDownloader() {
48-
return iconDownloader;
54+
public static IconDownloadService getIconDownloader() {
55+
return iconService;
4956
}
5057

51-
public static ModDownloader getModDownloader() {
52-
return modDownloader;
58+
public static ModDownloadService getModDownloader() {
59+
return modDownloadService;
60+
}
61+
62+
public static UpdateCheckService getUpdateChecker() {
63+
return updateCheckService;
5364
}
5465

5566
@Override
5667
public void onInitializeClient() {
5768
registerModProvider(new Modrinth());
5869
}
70+
71+
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);
74+
}
75+
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();
80+
}
81+
5982
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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.mod;
18+
19+
public enum ModState {
20+
21+
/**
22+
* Returns this if the mod has been found in the current
23+
* mod list
24+
*/
25+
INSTALLED,
26+
/**
27+
* Returns this if the mod has been found and also has been
28+
* checked for updates
29+
*/
30+
OUTDATED,
31+
/**
32+
* Returns this if the mod was not found
33+
*/
34+
DOWNLOADABLE,
35+
CHECKING
36+
37+
}

src/main/java/xyz/deathsgun/modmanager/api/mod/VersionType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
package xyz.deathsgun.modmanager.api.mod;
1818

1919
public enum VersionType {
20-
RELEASE, PRE_RELEASE;
20+
RELEASE, BETA;
2121

2222
public static VersionType fromString(String type) {
2323
return switch (type) {
24-
case "pre_release" -> PRE_RELEASE;
24+
case "beta" -> BETA;
2525
default -> RELEASE;
2626
};
2727
}

src/main/java/xyz/deathsgun/modmanager/api/provider/IModProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public interface IModProvider {
7070
* Returns a limited number of {@link SummarizedMod}'s from a given search.
7171
*
7272
* @param query the search string
73-
* @param page the current requested page starts at 1
73+
* @param page the current requested page starts at 0
7474
* @param limit the amount of mods to return
7575
* @return a list of mods matching the search term
7676
*/

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

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,30 @@
2222
import net.minecraft.client.font.TextRenderer;
2323
import net.minecraft.client.gui.DrawableHelper;
2424
import net.minecraft.client.util.math.MatrixStack;
25-
import net.minecraft.text.LiteralText;
26-
import net.minecraft.text.StringVisitable;
27-
import net.minecraft.text.Text;
25+
import net.minecraft.text.*;
2826
import net.minecraft.util.Identifier;
2927
import net.minecraft.util.Language;
3028
import org.jetbrains.annotations.NotNull;
3129
import xyz.deathsgun.modmanager.ModManager;
30+
import xyz.deathsgun.modmanager.api.mod.ModState;
3231
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
3332
import xyz.deathsgun.modmanager.gui.widget.better.BetterListWidget;
3433

34+
import java.util.concurrent.CompletableFuture;
35+
3536
public class ModListEntry extends BetterListWidget.BetterListEntry<ModListEntry> {
3637

3738
public static final Identifier UNKNOWN_ICON = new Identifier("textures/misc/unknown_pack.png");
3839
public static final Identifier LOADING_ICON = new Identifier("modmanager", "textures/gui/loading.png");
3940

4041
private final SummarizedMod mod;
4142
private final MinecraftClient client = MinecraftClient.getInstance();
43+
private ModState modState = ModState.CHECKING;
4244

4345
public ModListEntry(ModListWidget list, @NotNull SummarizedMod mod) {
4446
super(list, new LiteralText(mod.name()));
4547
this.mod = mod;
48+
CompletableFuture.runAsync(() -> this.modState = ModManager.getState(this.mod));
4649
}
4750

4851
@Override
@@ -62,12 +65,33 @@ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth
6265
StringVisitable trimmedName = name;
6366
int maxNameWidth = entryWidth - iconSize - 3;
6467
TextRenderer font = this.client.textRenderer;
65-
if (font.getWidth(name) > maxNameWidth) {
68+
69+
int primaryColor = 0xFFFFFF;
70+
int secondaryColor = 0xFFFFFF;
71+
OrderedText badgeText = null;
72+
if (modState == ModState.INSTALLED) {
73+
primaryColor = 0xff0e2a55;
74+
secondaryColor = 0xff2b4b7c;
75+
badgeText = new TranslatableText("modmanager.badge.installed").asOrderedText();
76+
maxNameWidth -= font.getWidth(badgeText) + 6;
77+
} else if (modState == ModState.OUTDATED) {
78+
primaryColor = 0xff530C17;
79+
secondaryColor = 0xff841426;
80+
badgeText = new TranslatableText("modmanager.badge.outdated").asOrderedText();
81+
maxNameWidth -= font.getWidth(badgeText) + 6;
82+
}
83+
84+
int textWidth = font.getWidth(name);
85+
if (textWidth > maxNameWidth) {
6686
StringVisitable ellipsis = StringVisitable.plain("...");
6787
trimmedName = StringVisitable.concat(font.trimToWidth(name, maxNameWidth - font.getWidth(ellipsis)), ellipsis);
6888
}
6989
font.draw(matrices, Language.getInstance().reorder(trimmedName), x + iconSize + 3, y + 1, 0xFFFFFF);
70-
DrawingUtil.drawWrappedString(matrices, mod.description(), (x + iconSize + 3 + 4), (y + client.textRenderer.fontHeight + 2), entryWidth - iconSize - 7, 2, 0x808080);
90+
if (badgeText != null) {
91+
DrawingUtil.drawBadge(matrices, x + iconSize + 3 + textWidth + 3, y + 1, font.getWidth(badgeText) + 6, badgeText, secondaryColor, primaryColor, 0xFFFFFF);
92+
}
93+
94+
DrawingUtil.drawWrappedString(matrices, mod.description(), (x + iconSize + 3 + 4), (y + client.textRenderer.fontHeight + 4), entryWidth - iconSize - 7, 2, 0x808080);
7195
}
7296

7397

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@
2020
import xyz.deathsgun.modmanager.ModManager;
2121
import xyz.deathsgun.modmanager.api.mod.Category;
2222
import xyz.deathsgun.modmanager.api.mod.SummarizedMod;
23-
import xyz.deathsgun.modmanager.downloader.IconDownloader;
2423
import xyz.deathsgun.modmanager.gui.ModsOverviewScreen;
2524
import xyz.deathsgun.modmanager.gui.widget.better.BetterListWidget;
25+
import xyz.deathsgun.modmanager.services.IconDownloadService;
2626

2727
import java.util.ArrayList;
2828
import java.util.Objects;
2929

3030
public class ModListWidget extends BetterListWidget<ModListEntry> {
3131

3232
private final int limit = 20;
33-
private final IconDownloader iconDownloader = new IconDownloader();
33+
private final IconDownloadService iconDownloadService = new IconDownloadService();
3434
private final ArrayList<SummarizedMod> mods = new ArrayList<>();
3535
private int page = 0;
3636
private Category category;
@@ -103,6 +103,6 @@ public void showPreviousPage() {
103103
}
104104

105105
public void close() {
106-
this.iconDownloader.destroyIcons();
106+
this.iconDownloadService.destroyIcons();
107107
}
108108
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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.mixin;
18+
19+
import net.minecraft.client.gui.screen.Screen;
20+
import net.minecraft.client.gui.screen.TitleScreen;
21+
import net.minecraft.client.toast.SystemToast;
22+
import net.minecraft.client.util.math.MatrixStack;
23+
import net.minecraft.text.Text;
24+
import net.minecraft.text.TranslatableText;
25+
import org.spongepowered.asm.mixin.Mixin;
26+
import org.spongepowered.asm.mixin.injection.At;
27+
import org.spongepowered.asm.mixin.injection.Inject;
28+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
29+
import xyz.deathsgun.modmanager.ModManager;
30+
31+
import java.util.Objects;
32+
33+
@Mixin(TitleScreen.class)
34+
public abstract class TitleScreenMixin extends Screen {
35+
36+
private boolean hasRun = false;
37+
38+
protected TitleScreenMixin(Text title) {
39+
super(title);
40+
}
41+
42+
@Inject(at = @At("TAIL"), method = "render")
43+
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) {
44+
if (hasRun) {
45+
return;
46+
}
47+
hasRun = true;
48+
if (!ModManager.getUpdateChecker().updatesAvailable()) {
49+
return;
50+
}
51+
Objects.requireNonNull(client).getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT,
52+
new TranslatableText("modmanager.toast.update.title"),
53+
new TranslatableText("modmanager.toast.update.description")));
54+
}
55+
56+
}

src/main/java/xyz/deathsgun/modmanager/providers/modrinth/Modrinth.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ public DetailedMod getMod(@NotNull String id) throws Exception {
137137

138138
@Override
139139
public List<ModVersion> getVersionsForMod(String id) throws Exception {
140-
ArrayList<ModVersion> result = new ArrayList<>();
141140
HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create(this.baseUrl + "/api/v1/mod/" + id + "/version")).build();
142141
HttpResponse<String> response = this.http.send(request, HttpResponse.BodyHandlers.ofString());
143142
if (response.statusCode() != 200) {

src/main/java/xyz/deathsgun/modmanager/downloader/IconDownloader.java renamed to src/main/java/xyz/deathsgun/modmanager/services/IconDownloadService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package xyz.deathsgun.modmanager.downloader;
17+
package xyz.deathsgun.modmanager.services;
1818

1919
import net.minecraft.client.MinecraftClient;
2020
import net.minecraft.client.texture.NativeImage;
@@ -33,7 +33,7 @@
3333
import java.util.ArrayList;
3434
import java.util.HashMap;
3535

36-
public class IconDownloader extends Thread {
36+
public class IconDownloadService extends Thread {
3737

3838
private final Logger logger = LogManager.getLogger("Icon Downloader");
3939
private final HashMap<String, SummarizedMod> mods = new HashMap<>();
@@ -42,7 +42,7 @@ public class IconDownloader extends Thread {
4242
private final ArrayList<String> errored = new ArrayList<>();
4343
private final HttpClient httpClient;
4444

45-
public IconDownloader() {
45+
public IconDownloadService() {
4646
this.httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(3)).build();
4747
setName("Icon downloader");
4848
start();

0 commit comments

Comments
 (0)