Skip to content

Commit 39f0fcf

Browse files
LostLumaProspector
authored andcommitted
Fix mods screen initialization being slow with many mods (#790)
- Fix Mods screen being slow to open the first time - Config screen errors no longer show until after a user has tried to open them
1 parent db0cb4e commit 39f0fcf

5 files changed

Lines changed: 53 additions & 49 deletions

File tree

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

Lines changed: 20 additions & 9 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

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

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -102,26 +102,6 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou
102102

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

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

543-
this.configureButton.active = modHasConfigScreen.get(modId);
522+
this.configureButton.active = getModHasConfigScreen(modId);
544523
this.configureButton.visible =
545-
selected != null && modHasConfigScreen.get(modId) || modScreenErrors.containsKey(modId);
524+
selected != null && getModHasConfigScreen(modId) || modScreenErrors.containsKey(modId);
546525

547526
if (modScreenErrors.containsKey(modId)) {
548527
Throwable e = modScreenErrors.get(modId);
@@ -652,7 +631,29 @@ private static boolean isValidMod(Path mod) {
652631
}
653632
}
654633

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

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

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

146142
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
@@ -124,8 +124,7 @@ public void render(
124124
}
125125

126126
if (!(this instanceof ParentEntry) && ModMenuConfig.QUICK_CONFIGURE.getValue() && (this.list.getParent()
127-
.getModHasConfigScreen()
128-
.get(modId) || this.list.getParent().modScreenErrors.containsKey(modId))) {
127+
.getModHasConfigScreen(modId) || this.list.getParent().modScreenErrors.containsKey(modId))) {
129128
final int textureSize = ModMenuConfig.COMPACT_LIST.getValue() ?
130129
(int) (256 / (FULL_ICON_SIZE / (double) COMPACT_ICON_SIZE)) :
131130
256;
@@ -167,9 +166,7 @@ public void render(
167166
@Override
168167
public boolean mouseClicked(double mouseX, double mouseY, int delta) {
169168
list.select(this);
170-
if (ModMenuConfig.QUICK_CONFIGURE.getValue() && this.list.getParent()
171-
.getModHasConfigScreen()
172-
.get(this.mod.getId())) {
169+
if (ModMenuConfig.QUICK_CONFIGURE.getValue() && this.list.getParent().getModHasConfigScreen(this.mod.getId())) {
173170
int iconSize = ModMenuConfig.COMPACT_LIST.getValue() ? COMPACT_ICON_SIZE : FULL_ICON_SIZE;
174171
if (mouseX - list.getRowLeft() <= iconSize) {
175172
this.openConfig();
@@ -182,7 +179,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int delta) {
182179
}
183180

184181
public void openConfig() {
185-
MinecraftClient.getInstance().setScreen(ModMenu.getConfigScreen(mod.getId(), list.getParent()));
182+
this.list.getParent().safelyOpenConfigScreen(mod.getId());
186183
}
187184

188185
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;

0 commit comments

Comments
 (0)