Rewrite main menu button injection code (closes #577, fixes #621)

For 1.16.4+ only because we use parts of fabric-screen-api.
This commit is contained in:
Jonas Herzig
2023-06-12 09:17:40 +02:00
parent f92d6f5281
commit 587eff59fe
4 changed files with 170 additions and 3 deletions

View File

@@ -275,8 +275,8 @@ dependencies {
11502: '0.5.1+build.294-1.15', 11502: '0.5.1+build.294-1.15',
11601: '0.14.0+build.371-1.16', 11601: '0.14.0+build.371-1.16',
11603: '0.17.1+build.394-1.16', 11603: '0.17.1+build.394-1.16',
11604: '0.25.1+build.416-1.16', 11604: '0.42.0+1.16',
11701: '0.37.1+1.17', 11701: '0.46.1+1.17',
11800: '0.43.1+1.18', 11800: '0.43.1+1.18',
11801: '0.43.1+1.18', 11801: '0.43.1+1.18',
11802: '0.47.9+1.18.2', 11802: '0.47.9+1.18.2',
@@ -296,6 +296,9 @@ dependencies {
fabricApiModules.remove("keybindings-v0") fabricApiModules.remove("keybindings-v0")
fabricApiModules.add("key-binding-api-v1") fabricApiModules.add("key-binding-api-v1")
} }
if (mcVersion >= 11604) {
fabricApiModules.add("screen-api-v1")
}
if (mcVersion >= 11700) { if (mcVersion >= 11700) {
fabricApiModules.remove("networking-v0") fabricApiModules.remove("networking-v0")
fabricApiModules.add("networking-api-v1") fabricApiModules.add("networking-api-v1")

2
jGui

Submodule jGui updated: 0fc98877c9...05f8ac3ed5

View File

@@ -12,6 +12,7 @@ public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
public static final SettingsRegistry.MultipleChoiceSettingKeys<String> CAMERA = public static final SettingsRegistry.MultipleChoiceSettingKeys<String> CAMERA =
new SettingsRegistry.MultipleChoiceSettingKeys<>( new SettingsRegistry.MultipleChoiceSettingKeys<>(
"replay", "camera", "replaymod.gui.settings.camera", "replaymod.camera.classic"); "replay", "camera", "replaymod.gui.settings.camera", "replaymod.camera.classic");
public static final Setting<Boolean> LEGACY_MAIN_MENU_BUTTON = new Setting<>("legacyMainMenuButton", false);
public static final SettingsRegistry.MultipleChoiceSettingKeys<String> MAIN_MENU_BUTTON = public static final SettingsRegistry.MultipleChoiceSettingKeys<String> MAIN_MENU_BUTTON =
new SettingsRegistry.MultipleChoiceSettingKeys<>( new SettingsRegistry.MultipleChoiceSettingKeys<>(
"replay", "mainMenuButton", null, MainMenuButtonPosition.DEFAULT.name()); "replay", "mainMenuButton", null, MainMenuButtonPosition.DEFAULT.name());

View File

@@ -16,6 +16,23 @@ import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.AbstractButtonWidget; import net.minecraft.client.gui.widget.AbstractButtonWidget;
//#if MC>=11904
//#else
import net.minecraft.client.MinecraftClient;
//#endif
//#if MC>=11903
//$$ import net.minecraft.client.gui.tooltip.Tooltip;
//#endif
//#if MC>=11604
import de.johni0702.minecraft.gui.MinecraftGuiRenderer;
import net.fabricmc.fabric.api.client.screen.v1.Screens;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.client.util.math.MatrixStack;
//#endif
//#if MC>=11600 //#if MC>=11600
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
@@ -36,6 +53,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -124,6 +142,7 @@ public class GuiHandler extends EventRegistrations {
b.getWidth(), b.getWidth(),
b.getHeight(), b.getHeight(),
"replaymod.gui.exit", "replaymod.gui.exit",
null,
this::onButton this::onButton
)); ));
} else if (id.equals(BUTTON_ADVANCEMENTS)) { } else if (id.equals(BUTTON_ADVANCEMENTS)) {
@@ -226,6 +245,116 @@ public class GuiHandler extends EventRegistrations {
return; return;
} }
//#if MC>=11604
if (mod.getCore().getSettingsRegistry().get(Setting.LEGACY_MAIN_MENU_BUTTON)) {
legacyInjectIntoMainMenu(guiScreen, buttonList);
} else {
properInjectIntoMainMenu(guiScreen);
}
//#else
//$$ legacyInjectIntoMainMenu(guiScreen, buttonList);
//#endif
}
//#if MC>=11604
private void properInjectIntoMainMenu(Screen screen) {
List<AbstractButtonWidget> buttonList = Screens.getButtons(screen);
MainMenuButtonPosition buttonPosition = MainMenuButtonPosition.valueOf(mod.getCore().getSettingsRegistry().get(Setting.MAIN_MENU_BUTTON));
// Workaround for FancyMenu v2 initializing the screen twice, likely fixed in v3
if (isFancyMenu2Installed()) {
for (AbstractButtonWidget button : buttonList) {
if (button instanceof InjectedButton) {
return;
}
}
}
Point pos;
if (buttonPosition == MainMenuButtonPosition.BIG) {
int x = screen.width / 2 - 100;
// We want to position our button below the realms button
Optional<AbstractButtonWidget> targetButton = findButton(buttonList, "menu.online", 14)
.map(Optional::of)
// or, if someone removed the realms button, we'll alternatively take the multiplayer one
.orElseGet(() -> findButton(buttonList, "menu.multiplayer", 2));
int y = targetButton
// if we found some button, put our button at its position (we'll move it out of the way shortly)
.map(it -> it.y)
// and if we can't even find that one, then just guess
.orElse(screen.height / 4 + 10 + 4 * 24);
// Move all buttons above or at our one upwards
moveAllButtonsInRect(buttonList,
x, x + 200,
Integer.MIN_VALUE, y,
-24);
pos = new Point(x, y);
} else {
pos = determineButtonPos(buttonPosition, screen, buttonList);
}
AbstractButtonWidget replayViewerButton;
if (buttonPosition == MainMenuButtonPosition.BIG) {
replayViewerButton = new InjectedButton(
screen, BUTTON_REPLAY_VIEWER,
pos.getX(), pos.getY(),
200, 20,
"replaymod.gui.replayviewer",
null,
this::onButton
);
} else {
replayViewerButton = new InjectedButton(
screen, BUTTON_REPLAY_VIEWER,
pos.getX(), pos.getY(),
20, 20,
"",
"replaymod.gui.replayviewer",
this::onButton
) {
@Override
//#if MC>=11904
//$$ public void renderButton(MatrixStack context, int mouseX, int mouseY, float delta) {
//$$ super.renderButton(context, mouseX, mouseY, delta);
//#else
protected void renderBg(MatrixStack context, MinecraftClient client, int mouseX, int mouseY) {
super.renderBg(context, client, mouseX, mouseY);
//#endif
MinecraftGuiRenderer renderer = new MinecraftGuiRenderer(context);
renderer.bindTexture(GuiReplayButton.ICON);
renderer.drawTexturedRect(
this.x + 3, this.y + 3,
0, 0,
this.width - 6, this.height - 6,
1, 1,
1, 1
);
}
};
}
int index = determineButtonIndex(buttonList, replayViewerButton);
if (index != -1) {
buttonList.add(index, replayViewerButton);
} else {
buttonList.add(replayViewerButton);
}
}
private boolean isFancyMenu2Installed() {
ModContainer mod = FabricLoader.getInstance().getModContainer("fancymenu").orElse(null);
if (mod == null) {
return false;
}
return mod.getMetadata().getVersion().getFriendlyString().startsWith("2.");
}
//#endif
private void legacyInjectIntoMainMenu(Screen guiScreen, Collection<AbstractButtonWidget> buttonList) {
boolean isCustomMainMenuMod = guiScreen.getClass().getName().endsWith("custommainmenu.gui.GuiFakeMain"); boolean isCustomMainMenuMod = guiScreen.getClass().getName().endsWith("custommainmenu.gui.GuiFakeMain");
MainMenuButtonPosition buttonPosition = MainMenuButtonPosition.valueOf(mod.getCore().getSettingsRegistry().get(Setting.MAIN_MENU_BUTTON)); MainMenuButtonPosition buttonPosition = MainMenuButtonPosition.valueOf(mod.getCore().getSettingsRegistry().get(Setting.MAIN_MENU_BUTTON));
@@ -280,6 +409,7 @@ public class GuiHandler extends EventRegistrations {
200, 200,
20, 20,
"replaymod.gui.replayviewer", "replaymod.gui.replayviewer",
null,
this::onButton this::onButton
); );
//#if FABRIC<=0 //#if FABRIC<=0
@@ -356,6 +486,27 @@ public class GuiHandler extends EventRegistrations {
} }
} }
private int determineButtonIndex(Collection<AbstractButtonWidget> buttons, AbstractButtonWidget button) {
AbstractButtonWidget best = null;
int bestIndex = -1;
int index = 0;
for (AbstractButtonWidget other : buttons) {
if (other.y > button.y || other.y == button.y && other.x > button.x) {
index++;
continue;
}
if (best == null || other.y > best.y || other.y == best.y && other.x > best.x) {
best = other;
bestIndex = index + 1;
}
index++;
}
return bestIndex;
}
//#if MC>=11400 //#if MC>=11400
private void onButton(InjectedButton button) { private void onButton(InjectedButton button) {
Screen guiScreen = button.guiScreen; Screen guiScreen = button.guiScreen;
@@ -396,6 +547,7 @@ public class GuiHandler extends EventRegistrations {
public final int id; public final int id;
private Consumer<InjectedButton> onClick; private Consumer<InjectedButton> onClick;
public InjectedButton(Screen guiScreen, int buttonId, int x, int y, int width, int height, String buttonText, public InjectedButton(Screen guiScreen, int buttonId, int x, int y, int width, int height, String buttonText,
String tooltip,
//#if MC>=11400 //#if MC>=11400
Consumer<InjectedButton> onClick Consumer<InjectedButton> onClick
//#else //#else
@@ -418,6 +570,11 @@ public class GuiHandler extends EventRegistrations {
//#if MC>=11400 //#if MC>=11400
, self -> onClick.accept((InjectedButton) self) , self -> onClick.accept((InjectedButton) self)
//#endif //#endif
//#if MC>=11600 && MC<11903
, tooltip != null
? (button, matrices, mouseX, mouseY) -> guiScreen.renderTooltip(matrices, new TranslatableText(tooltip), mouseX, mouseY)
: EMPTY
//#endif
//#if MC>=11903 //#if MC>=11903
//$$ , DEFAULT_NARRATION_SUPPLIER //$$ , DEFAULT_NARRATION_SUPPLIER
//#endif //#endif
@@ -429,6 +586,12 @@ public class GuiHandler extends EventRegistrations {
//#else //#else
//$$ this.onClick = null; //$$ this.onClick = null;
//#endif //#endif
//#if MC>=11903
//$$ if (tooltip != null) {
//$$ setTooltip(Tooltip.of(Text.translatable(tooltip)));
//$$ }
//#endif
} }
//#if MC>=11400 && MC<11400 //#if MC>=11400 && MC<11400