Skip to content

Commit f900e42

Browse files
committed
Merge branch '1.21' into 1.21.2
# Conflicts: # gradle.properties
2 parents c532d3f + 39f0fcf commit f900e42

31 files changed

Lines changed: 265 additions & 171 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Mod Menu
2-
![Screenshot of the Mods screen, showing a list of a few mods on the left side below a search bar and filters button, where Mod Menu is selected. On the right side of the screen, it shows more details about the mod, such as authors, a description, links, credits, and a button to configure the mod.](https://cdn.modrinth.com/data/mOgUt4GM/images/1b837be3f93c3e99e0ab70600698bd9f37723cec.png)
2+
![Screenshot of the Mods screen, showing a list of a few mods on the left side below a search bar and filters button, where Mod Menu is selected. On the right side of the screen, it shows more details about the mod, such as authors, a description, links, credits, and a button to configure the mod.](res/screenshot1.jpg)
33

44
Mod Menu lets you view the mods you have installed and, if supported by the mod, enables quick and easy access to the mod's config screens.
55

res/screenshot1.jpg

465 KB
Loading

src/main/java/com/terraformersmc/modmenu/ModMenu.java

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import net.minecraft.client.resource.language.I18n;
2626
import net.minecraft.text.MutableText;
2727
import net.minecraft.text.Text;
28+
import org.jetbrains.annotations.Nullable;
2829
import org.slf4j.Logger;
2930
import org.slf4j.LoggerFactory;
3031

@@ -59,21 +60,31 @@ public class ModMenu implements ClientModInitializer {
5960
public static final boolean DEV_ENVIRONMENT = FabricLoader.getInstance().isDevelopmentEnvironment();
6061
public static final boolean TEXT_PLACEHOLDER_COMPAT = FabricLoader.getInstance().isModLoaded("placeholder-api");
6162

62-
public static Screen getConfigScreen(String modid, Screen menuScreen) {
63+
public static boolean hasConfigScreen(String modId) {
64+
return getConfigScreenFactory(modId) != null;
65+
}
66+
67+
public static @Nullable Screen getConfigScreen(String modId, Screen parent) {
68+
ConfigScreenFactory<?> factory = getConfigScreenFactory(modId);
69+
if (factory != null) {
70+
return factory.create(parent);
71+
}
72+
return null;
73+
}
74+
75+
private static @Nullable ConfigScreenFactory<?> getConfigScreenFactory(String modId) {
76+
if (ModMenuConfig.HIDDEN_CONFIGS.getValue().contains(modId)) {
77+
return null;
78+
}
79+
6380
for (ModMenuApi api : apiImplementations) {
6481
var factoryProviders = api.getProvidedConfigScreenFactories();
6582
if (!factoryProviders.isEmpty()) {
6683
factoryProviders.forEach(configScreenFactories::putIfAbsent);
6784
}
6885
}
69-
if (ModMenuConfig.HIDDEN_CONFIGS.getValue().contains(modid)) {
70-
return null;
71-
}
72-
ConfigScreenFactory<?> factory = configScreenFactories.get(modid);
73-
if (factory != null) {
74-
return factory.create(menuScreen);
75-
}
76-
return null;
86+
87+
return configScreenFactories.get(modId);
7788
}
7889

7990
@Override
@@ -127,21 +138,46 @@ public void onInitializeClient() {
127138
Map<String, Mod> dummyParents = new HashMap<>();
128139

129140
// Initialize parent map
141+
HashSet<String> modParentSet = new HashSet<>();
130142
for (Mod mod : MODS.values()) {
131143
String parentId = mod.getParent();
132-
if (parentId != null) {
133-
Mod parent = MODS.getOrDefault(parentId, dummyParents.get(parentId));
144+
if (parentId == null) {
145+
ROOT_MODS.put(mod.getId(), mod);
146+
continue;
147+
}
148+
149+
Mod parent;
150+
modParentSet.clear();
151+
while (true) {
152+
parent = MODS.getOrDefault(parentId, dummyParents.get(parentId));
134153
if (parent == null) {
135154
if (mod instanceof FabricMod) {
136155
parent = new FabricDummyParentMod((FabricMod) mod, parentId);
137156
dummyParents.put(parentId, parent);
138157
}
139158
}
140-
PARENT_MAP.put(parent, mod);
141-
} else {
159+
160+
parentId = parent != null ? parent.getParent() : null;
161+
if (parentId == null) {
162+
// It will most likely end here in the first iteration
163+
break;
164+
}
165+
166+
if (modParentSet.contains(parentId)) {
167+
LOGGER.warn("Mods contain each other as parents: {}", modParentSet);
168+
parent = null;
169+
break;
170+
}
171+
modParentSet.add(parentId);
172+
}
173+
174+
if (parent == null) {
142175
ROOT_MODS.put(mod.getId(), mod);
176+
continue;
143177
}
178+
PARENT_MAP.put(parent, mod);
144179
}
180+
145181
MODS.putAll(dummyParents);
146182
ModMenuEventHandler.register();
147183
}

src/main/java/com/terraformersmc/modmenu/gui/ModsScreen.java

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,6 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou
103103

104104
@Override
105105
protected void init() {
106-
for (Mod mod : ModMenu.MODS.values()) {
107-
String id = mod.getId();
108-
if (!modHasConfigScreen.containsKey(id)) {
109-
try {
110-
Screen configScreen = ModMenu.getConfigScreen(id, this);
111-
modHasConfigScreen.put(id, configScreen != null);
112-
} catch (java.lang.NoClassDefFoundError e) {
113-
LOGGER.warn(
114-
"The '" + id + "' mod config screen is not available because " + e.getLocalizedMessage() +
115-
" is missing.");
116-
modScreenErrors.put(id, e);
117-
modHasConfigScreen.put(id, false);
118-
} catch (Throwable e) {
119-
LOGGER.error("Error from mod '" + id + "'", e);
120-
modScreenErrors.put(id, e);
121-
modHasConfigScreen.put(id, false);
122-
}
123-
}
124-
}
125-
126106
int paneY = ModMenuConfig.CONFIG_MODE.getValue() ? 48 : 48 + 19;
127107
this.paneWidth = this.width / 2 - 8;
128108
this.rightPaneX = this.width - this.paneWidth;
@@ -204,9 +184,8 @@ protected void init() {
204184
if (!ModMenuConfig.HIDE_CONFIG_BUTTONS.getValue()) {
205185
this.configureButton = LegacyTexturedButtonWidget.legacyTexturedBuilder(ScreenTexts.EMPTY, button -> {
206186
final String id = Objects.requireNonNull(selected).getMod().getId();
207-
if (modHasConfigScreen.get(id)) {
208-
Screen configScreen = ModMenu.getConfigScreen(id, this);
209-
client.setScreen(configScreen);
187+
if (getModHasConfigScreen(id)) {
188+
this.safelyOpenConfigScreen(id);
210189
} else {
211190
button.active = false;
212191
}
@@ -541,9 +520,9 @@ public void updateSelectedEntry(ModListEntry entry) {
541520

542521
if (this.configureButton != null) {
543522

544-
this.configureButton.active = modHasConfigScreen.get(modId);
523+
this.configureButton.active = getModHasConfigScreen(modId);
545524
this.configureButton.visible =
546-
selected != null && modHasConfigScreen.get(modId) || modScreenErrors.containsKey(modId);
525+
selected != null && getModHasConfigScreen(modId) || modScreenErrors.containsKey(modId);
547526

548527
if (modScreenErrors.containsKey(modId)) {
549528
Throwable e = modScreenErrors.get(modId);
@@ -601,7 +580,7 @@ public void filesDragged(List<Path> paths) {
601580
Path modsDirectory = FabricLoader.getInstance().getGameDir().resolve("mods");
602581

603582
// Filter out none mods
604-
List<Path> mods = paths.stream().filter(ModsScreen::isFabricMod).collect(Collectors.toList());
583+
List<Path> mods = paths.stream().filter(ModsScreen::isValidMod).collect(Collectors.toList());
605584

606585
if (mods.isEmpty()) {
607586
return;
@@ -631,23 +610,51 @@ public void filesDragged(List<Path> paths) {
631610
SystemToast.add(client.getToastManager(),
632611
SystemToast.Type.PERIODIC_NOTIFICATION,
633612
ModMenuScreenTexts.DROP_SUCCESSFUL_LINE_1,
634-
ModMenuScreenTexts.DROP_SUCCESSFUL_LINE_1
613+
ModMenuScreenTexts.DROP_SUCCESSFUL_LINE_2
635614
);
636615
}
637616
}
638617
this.client.setScreen(this);
639618
}, ModMenuScreenTexts.DROP_CONFIRM, Text.literal(modList)));
640619
}
641620

642-
private static boolean isFabricMod(Path mod) {
621+
private static boolean isValidMod(Path mod) {
643622
try (JarFile jarFile = new JarFile(mod.toFile())) {
644-
return jarFile.getEntry("fabric.mod.json") != null;
623+
var isFabricMod = jarFile.getEntry("fabric.mod.json") != null;
624+
625+
if (!ModMenu.RUNNING_QUILT) {
626+
return isFabricMod;
627+
} else {
628+
return isFabricMod || jarFile.getEntry("quilt.mod.json") != null;
629+
}
645630
} catch (IOException e) {
646631
return false;
647632
}
648633
}
649634

650-
public Map<String, Boolean> getModHasConfigScreen() {
651-
return this.modHasConfigScreen;
635+
public boolean getModHasConfigScreen(String modId) {
636+
if (this.modScreenErrors.containsKey(modId)) {
637+
return false;
638+
} else {
639+
return this.modHasConfigScreen.computeIfAbsent(modId, ModMenu::hasConfigScreen);
640+
}
641+
}
642+
643+
public void safelyOpenConfigScreen(String modId) {
644+
try {
645+
Screen screen = ModMenu.getConfigScreen(modId, this);
646+
647+
if (screen != null) {
648+
this.client.setScreen(screen);
649+
}
650+
} catch (java.lang.NoClassDefFoundError e) {
651+
LOGGER.warn(
652+
"The '" + modId + "' mod config screen is not available because " + e.getLocalizedMessage() +
653+
" is missing.");
654+
modScreenErrors.put(modId, e);
655+
} catch (Throwable e) {
656+
LOGGER.error("Error from mod '" + modId + "'", e);
657+
modScreenErrors.put(modId, e);
658+
}
652659
}
653660
}

src/main/java/com/terraformersmc/modmenu/gui/widget/ModListWidget.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,7 @@ private void filter(String searchTerm, boolean refresh, boolean search) {
137137
addedMods.clear();
138138
Collection<Mod> mods = ModMenu.MODS.values().stream().filter(mod -> {
139139
if (ModMenuConfig.CONFIG_MODE.getValue()) {
140-
Map<String, Boolean> modHasConfigScreen = parent.getModHasConfigScreen();
141-
var hasConfig = modHasConfigScreen.get(mod.getId());
142-
if (!hasConfig) {
143-
return false;
144-
}
140+
return !parent.getModHasConfigScreen(mod.getId());
145141
}
146142

147143
return !mod.isHidden();

src/main/java/com/terraformersmc/modmenu/gui/widget/entries/ModListEntry.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ public void render(
125125
}
126126

127127
if (!(this instanceof ParentEntry) && ModMenuConfig.QUICK_CONFIGURE.getValue() && (this.list.getParent()
128-
.getModHasConfigScreen()
129-
.get(modId) || this.list.getParent().modScreenErrors.containsKey(modId))) {
128+
.getModHasConfigScreen(modId) || this.list.getParent().modScreenErrors.containsKey(modId))) {
130129
final int textureSize = ModMenuConfig.COMPACT_LIST.getValue() ?
131130
(int) (256 / (FULL_ICON_SIZE / (double) COMPACT_ICON_SIZE)) :
132131
256;
@@ -168,9 +167,7 @@ public void render(
168167
@Override
169168
public boolean mouseClicked(double mouseX, double mouseY, int delta) {
170169
list.select(this);
171-
if (ModMenuConfig.QUICK_CONFIGURE.getValue() && this.list.getParent()
172-
.getModHasConfigScreen()
173-
.get(this.mod.getId())) {
170+
if (ModMenuConfig.QUICK_CONFIGURE.getValue() && this.list.getParent().getModHasConfigScreen(this.mod.getId())) {
174171
int iconSize = ModMenuConfig.COMPACT_LIST.getValue() ? COMPACT_ICON_SIZE : FULL_ICON_SIZE;
175172
if (mouseX - list.getRowLeft() <= iconSize) {
176173
this.openConfig();
@@ -183,7 +180,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int delta) {
183180
}
184181

185182
public void openConfig() {
186-
MinecraftClient.getInstance().setScreen(ModMenu.getConfigScreen(mod.getId(), list.getParent()));
183+
this.list.getParent().safelyOpenConfigScreen(mod.getId());
187184
}
188185

189186
public Mod getMod() {

src/main/java/com/terraformersmc/modmenu/util/mod/ModSearch.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ private static int passesFilters(ModsScreen screen, Mod mod, String query) {
6868
|| deprecated.contains(query) && mod.getBadges()
6969
.contains(Mod.Badge.DEPRECATED) // Search for deprecated mods
7070
|| clientside.contains(query) && mod.getBadges().contains(Mod.Badge.CLIENT) // Search for clientside mods
71-
|| configurable.contains(query) && screen.getModHasConfigScreen()
72-
.get(modId) // Search for mods that can be configured
71+
|| configurable.contains(query) && screen.getModHasConfigScreen(modId) // Search for mods that can be configured
7372
|| hasUpdate.contains(query) && mod.hasUpdate() // Search for mods that have updates
7473
) {
7574
return 1;
-11 Bytes
Loading
-23 Bytes
Loading
-6 Bytes
Loading

0 commit comments

Comments
 (0)