Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c1b0897
Make hardcoded text translatable
StarmanMine142 Sep 26, 2026
47dee80
Update ModListScreen.java
StarmanMine142 Sep 26, 2026
ac46e10
Update ModListWidget.java
StarmanMine142 Sep 26, 2026
5cc4e9b
Update EntryListWidget.java
StarmanMine142 Sep 26, 2026
454d334
Update DescriptionListWidget.java
StarmanMine142 Sep 27, 2026
a126746
Update ModListEntry.java
StarmanMine142 Sep 27, 2026
c5010ea
Update ModListScreen.java
StarmanMine142 Sep 27, 2026
f10187b
Update en_US.lang
StarmanMine142 Sep 27, 2026
6cfd00c
Update ModListScreen.java
StarmanMine142 Sep 27, 2026
bb6fde2
Update HardcodedUtil.java
StarmanMine142 Sep 28, 2026
2648d1a
Update ModListScreen.java
StarmanMine142 Sep 28, 2026
df9918a
Update DescriptionListWidget.java
StarmanMine142 Sep 28, 2026
6ace480
Update HardcodedUtil.java
StarmanMine142 Sep 28, 2026
d105283
Update DescriptionListWidget.java
StarmanMine142 Oct 3, 2026
eabac7f
Update en_US.lang
StarmanMine142 Oct 3, 2026
594828d
Update ModListScreen.java
StarmanMine142 Oct 4, 2026
1a7f705
remove harcoded util
StarmanMine142 Oct 4, 2026
83b4a6f
Update en_US.lang
StarmanMine142 Oct 4, 2026
2f6d126
Update DescriptionListWidget.java
StarmanMine142 Oct 4, 2026
41adc87
Update ModListEntry.java
StarmanMine142 Oct 4, 2026
c8be18f
Update ModMenuConfig.java
StarmanMine142 Oct 4, 2026
f21ff5b
Update ModListSearch.java
StarmanMine142 Oct 4, 2026
72f175f
Update ModListEntry.java
StarmanMine142 Oct 4, 2026
7bbaffe
Update ModMenu.java
StarmanMine142 Oct 4, 2026
78a0e6a
Update en_US.lang
StarmanMine142 Oct 4, 2026
e327f4d
Update ModMenuConfig.java
StarmanMine142 Oct 5, 2026
8586917
Update en_US.lang
StarmanMine142 Oct 5, 2026
cbc3647
remove unique badge
StarmanMine142 Oct 5, 2026
eec369a
Search mod description
StarmanMine142 Oct 5, 2026
8dee600
remove unnecessary @SuppressWarnings
StarmanMine142 Oct 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/main/java/io/github/prospector/modmenu/ModMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.google.gson.GsonBuilder;
import io.github.prospector.modmenu.api.ModMenuApi;
import io.github.prospector.modmenu.config.ModMenuConfigManager;
import io.github.prospector.modmenu.util.HardcodedUtil;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
Expand Down Expand Up @@ -88,7 +87,6 @@ public void onInitialize() {
});
configScreenFactories.put("minecraft", (screenBase -> new ScreenOptions(screenBase, OptionsPages.GENERAL)));
Collection<ModContainer> mods = FabricLoader.getInstance().getAllMods();
HardcodedUtil.initializeHardcodings();
for (ModContainer mod : mods) {
ModMetadata metadata = mod.getMetadata();
String id = metadata.getId();
Expand Down Expand Up @@ -129,8 +127,14 @@ public void onInitialize() {
list.add(mod);
});
}
} else {
HardcodedUtil.hardcodeModuleMetadata(mod, metadata, id);
}

// Hardcode marking as library
if (id.equals("fabricloader")
|| id.equals("fabric")
|| id.equals("java")
|| id.equals("mixinextras")) {
addLibraryMod(id);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.prospector.modmenu.config;


import io.github.prospector.modmenu.util.HardcodedUtil;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.core.lang.I18n;

Expand Down Expand Up @@ -30,8 +29,8 @@ public Sorting getSorting() {
}

public enum Sorting {
ASCENDING(Comparator.comparing(modContainer -> HardcodedUtil.formatFabricModuleName(modContainer.getMetadata().getName())), "modmenu.sorting.ascending"),
DECENDING(ASCENDING.getComparator().reversed(), "modmenu.sorting.decending");
ASCENDING(Comparator.comparing(modContainer -> modContainer.getMetadata().getName(), String.CASE_INSENSITIVE_ORDER),"modmenu.sorting.ascending"),
DESCENDING(ASCENDING.getComparator().reversed(),"modmenu.sorting.descending");

final Comparator<ModContainer> comparator;
final String key;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package io.github.prospector.modmenu.gui;


import io.github.prospector.modmenu.util.HardcodedUtil;
import io.github.prospector.modmenu.util.RenderUtils;
import net.fabricmc.loader.api.metadata.ContactInformation;
import net.fabricmc.loader.api.metadata.Person;
import net.minecraft.client.Minecraft;
import net.minecraft.client.render.font.FontRenderer;
import net.minecraft.client.util.helper.UrlHelper;
import net.minecraft.core.lang.I18n;
import net.minecraft.core.net.command.TextFormatting;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class DescriptionListWidget extends EntryListWidget<DescriptionListWidget.DescriptionEntry> {
private final ModListScreen parent;
Expand Down Expand Up @@ -36,6 +40,37 @@ protected int getScrollbarPosition() {
return this.width - 6 + left;
}

protected class LinkEntry extends DescriptionEntry {
private final String link;
private final int indent;
private int lastRenderX;
private int lastRenderY;

public LinkEntry(String text, String link, int indent) {
super(text);
this.link = link;
this.indent = indent;
}

@Override
public void render(int index, int y, int x, int itemWidth, int itemHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
this.lastRenderX = x + indent;
this.lastRenderY = y;

String formattedText = TextFormatting.formatted(text, TextFormatting.BLUE, TextFormatting.UNDERLINE);
this.drawStringShadow(this.fontRenderer, formattedText, lastRenderX, lastRenderY, 0xFFFFFF);
}

public void mouseClicked(int mouseX, int mouseY, int button) {
if (button == 0) {
int textWidth = fontRenderer.stringWidth(text);
if (mouseX >= lastRenderX && mouseX <= lastRenderX + textWidth && mouseY >= lastRenderY && mouseY <= lastRenderY + 12) {
UrlHelper.openURL(link);
}
}
}
}

@Override
public void render(int mouseX, int mouseY, float delta) {
I18n i18n = I18n.getInstance();
Expand All @@ -44,33 +79,85 @@ public void render(int mouseX, int mouseY, float delta) {
lastSelected = selectedEntry;
clearEntries();
setScrollAmount(-Double.MAX_VALUE);
String description = lastSelected.getMetadata().getDescription();
String id = lastSelected.getMetadata().getId();
Collection<Person> authors = lastSelected.getMetadata().getAuthors();
Collection<Person> contributors = lastSelected.getMetadata().getContributors();
Collection<String> licenses = lastSelected.getMetadata().getLicense();
if (description.isEmpty() && HardcodedUtil.getHardcodedDescriptions().containsKey(id)) {
description = HardcodedUtil.getHardcodedDescription(id);
String id = selectedEntry.getMetadata().getId();
String descKey = "modmenu.descriptionTranslation." + id;
String translatedDesc = i18n.translateKey(descKey);

String description;
if (!translatedDesc.equals(descKey)) {
description = translatedDesc;
} else {
description = selectedEntry.getMetadata().getDescription();
}

if ("java".equals(id)) {
String vendor = System.getProperty("java.vendor", "Unknown Vendor");
String javaDist = i18n.translateKeyAndFormat("modmenu.javaDistributionName", vendor);
description = (description != null ? description : "") + "\n" + javaDist;
}

if (lastSelected != null && description != null && !description.isEmpty()) {
for (String line : RenderUtils.INSTANCE.wrapStringToWidthAsList(textRenderer, description.replaceAll("\n", "\n\n"), getRowWidth())) {
children().add(new DescriptionEntry(line));
String[] paragraphs = description.split("\r?\n");
for (String paragraph : paragraphs) {
if (paragraph.isEmpty()) {
children().add(new DescriptionEntry(""));
continue;
}
for (String line : RenderUtils.INSTANCE.wrapStringToWidthAsList(textRenderer, paragraph, getRowWidth())) {
children().add(new DescriptionEntry(line));
}
}
}

Collection<Person> authors = selectedEntry.getMetadata().getAuthors();
Collection<Person> contributors = selectedEntry.getMetadata().getContributors();
Collection<String> licenses = selectedEntry.getMetadata().getLicense();

if (!authors.isEmpty()) {
if (!children().isEmpty()) children().add(new DescriptionEntry(""));
children().add(new DescriptionEntry(i18n.translateKey("modmenu.authors")));
for (Person person : authors) {
children().add(new DescriptionEntry(" " + person.getName()));
}
}

if (!contributors.isEmpty()) {
if (!children().isEmpty()) children().add(new DescriptionEntry(""));
children().add(new DescriptionEntry(i18n.translateKey("modmenu.contributors")));
for (Person person : contributors) {
children().add(new DescriptionEntry(" " + person.getName()));
}
}

ContactInformation contact = selectedEntry.getMetadata().getContact();
Map<String, String> links = new HashMap<>(contact.asMap());

links.remove("homepage");
links.remove("issues");

if (!links.isEmpty()) {
children().add(new DescriptionEntry(""));

for (String line : RenderUtils.INSTANCE.wrapStringToWidthAsList(textRenderer, i18n.translateKey("modmenu.links"), getRowWidth())) {
children().add(new DescriptionEntry(line));
}

links.forEach((key, value) -> {
int indent = 8;
String translationKey = "modmenu." + key;
String translatedKey = i18n.translateKey(translationKey);

if (translatedKey.equals(translationKey)) {
translatedKey = Character.toUpperCase(key.charAt(0)) + key.substring(1);
}

for (String line : RenderUtils.INSTANCE.wrapStringToWidthAsList(textRenderer, translatedKey, getRowWidth() - 16)) {
children().add(new LinkEntry(line, value, indent));
indent = 16;
}
});
}

if (!licenses.isEmpty()) {
if (!children().isEmpty()) children().add(new DescriptionEntry(""));
children().add(new DescriptionEntry(i18n.translateKey("modmenu.licenses")));
Expand All @@ -82,6 +169,16 @@ public void render(int mouseX, int mouseY, float delta) {
super.render(mouseX, mouseY, delta);
}

@Override
public void mouseClicked(int mouseX, int mouseY, int button) {
super.mouseClicked(mouseX, mouseY, button);
for (DescriptionEntry entry : children()) {
if (entry instanceof LinkEntry) {
entry.mouseClicked(mouseX, mouseY, button);
}
}
}

@Override
protected void renderHoleBackground(int y1, int y2, int startAlpha, int endAlpha) {
// Awful hack but it makes the background "seamless"
Expand Down
42 changes: 19 additions & 23 deletions src/main/java/io/github/prospector/modmenu/gui/EntryListWidget.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.List;
import java.util.Objects;

@SuppressWarnings({"unchecked", "unused"})
@SuppressWarnings({"unused"})
@Environment(EnvType.CLIENT)
public abstract class EntryListWidget<E extends EntryListWidget.Entry<E>> extends Screen {
protected static final int DRAG_OUTSIDE = -2;
Expand All @@ -39,7 +39,7 @@ public abstract class EntryListWidget<E extends EntryListWidget.Entry<E>> extend
protected boolean renderSelection = true;
protected boolean renderHeader;
protected int headerHeight;
private boolean scrolling;
protected boolean scrolling;
private E selected;

private E focused;
Expand Down Expand Up @@ -168,7 +168,6 @@ protected void renderDecorations(int i, int j) {
}

public void render(int i, int j, float f) {
oldY = j;
this.renderBackground();
int k = this.getScrollbarPosition();
int l = k + 6;
Expand Down Expand Up @@ -321,25 +320,25 @@ protected int getScrollbarPosition() {
return this.width / 2 + 124;
}

@Override
@Override
public void mouseClicked(int d, int e, int i) {
this.updateScrollingState(d, e, i);
if (this.isMouseOver(d, e)) {
E entry = this.getEntryAtPosition(d, e);
if (entry != null) {
if (entry.list.getFocused() != null) {
if (!entry.list.getFocused().equals(entry)) {
this.focused = entry;
this.selected = entry;
this.dragging = true;
super.mouseClicked(d, e, i);
}
} else {
this.focused = entry;
this.selected = entry;
this.dragging = true;
super.mouseClicked(d, e, i);
}
if (entry.list.getFocused() != null) {
if (!entry.list.getFocused().equals(entry)) {
this.focused = entry;
this.selected = entry;
this.dragging = true;
super.mouseClicked(d, e, i);
}
} else {
this.focused = entry;
this.selected = entry;
this.dragging = true;
super.mouseClicked(d, e, i);
}
} else if (i == 0) {
this.clickedHeader((int)(d - (double)(this.left + this.width / 2 - this.getRowWidth() / 2)), (int)(e - (double)this.top) + (int)this.getScrollAmount() - 4);
}
Expand All @@ -353,14 +352,12 @@ public boolean mouseReleased(double d, double e, int i) {
return false;
}

double oldY = -1;
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double mouseDX, double mouseDY) {
if (mouseButton == 0 && isMouseOver(mouseX, mouseY)) {
setScrollAmount(getScrollAmount() - mouseY + oldY);
if (this.scrolling) {
setScrollAmount(getScrollAmount() - mouseDY);
return true;
} else {
return false;
}
return false;
}

public boolean mouseScrolled(double d, double e, double f) {
Expand Down Expand Up @@ -578,6 +575,5 @@ public boolean charTyped(char c, int i) {
public boolean changeFocus(boolean bl) {
return false;
}

}
}
Loading