diff --git a/build.gradle b/build.gradle index 245c2fa7..89f29de0 100644 --- a/build.gradle +++ b/build.gradle @@ -275,8 +275,8 @@ dependencies { 11502: '0.5.1+build.294-1.15', 11601: '0.14.0+build.371-1.16', 11603: '0.17.1+build.394-1.16', - 11604: '0.25.1+build.416-1.16', - 11701: '0.37.1+1.17', + 11604: '0.42.0+1.16', + 11701: '0.46.1+1.17', 11800: '0.43.1+1.18', 11801: '0.43.1+1.18', 11802: '0.47.9+1.18.2', @@ -296,6 +296,9 @@ dependencies { fabricApiModules.remove("keybindings-v0") fabricApiModules.add("key-binding-api-v1") } + if (mcVersion >= 11604) { + fabricApiModules.add("screen-api-v1") + } if (mcVersion >= 11700) { fabricApiModules.remove("networking-v0") fabricApiModules.add("networking-api-v1") diff --git a/jGui b/jGui index 0fc98877..05f8ac3e 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 0fc98877c977f3bcce5d7ccfd5f4dd26131ba3e5 +Subproject commit 05f8ac3ed5fc370058ce4d80ead71e82a7cecb54 diff --git a/src/main/java/com/replaymod/replay/Setting.java b/src/main/java/com/replaymod/replay/Setting.java index b2303c61..643f3834 100644 --- a/src/main/java/com/replaymod/replay/Setting.java +++ b/src/main/java/com/replaymod/replay/Setting.java @@ -12,6 +12,7 @@ public final class Setting extends SettingsRegistry.SettingKeys { public static final SettingsRegistry.MultipleChoiceSettingKeys CAMERA = new SettingsRegistry.MultipleChoiceSettingKeys<>( "replay", "camera", "replaymod.gui.settings.camera", "replaymod.camera.classic"); + public static final Setting LEGACY_MAIN_MENU_BUTTON = new Setting<>("legacyMainMenuButton", false); public static final SettingsRegistry.MultipleChoiceSettingKeys MAIN_MENU_BUTTON = new SettingsRegistry.MultipleChoiceSettingKeys<>( "replay", "mainMenuButton", null, MainMenuButtonPosition.DEFAULT.name()); diff --git a/src/main/java/com/replaymod/replay/handler/GuiHandler.java b/src/main/java/com/replaymod/replay/handler/GuiHandler.java index a8fec2a3..8e9def31 100644 --- a/src/main/java/com/replaymod/replay/handler/GuiHandler.java +++ b/src/main/java/com/replaymod/replay/handler/GuiHandler.java @@ -16,6 +16,23 @@ import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.Screen; 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 import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; @@ -36,6 +53,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; +import java.util.List; import java.util.Optional; import java.util.function.Consumer; import java.util.stream.Stream; @@ -124,6 +142,7 @@ public class GuiHandler extends EventRegistrations { b.getWidth(), b.getHeight(), "replaymod.gui.exit", + null, this::onButton )); } else if (id.equals(BUTTON_ADVANCEMENTS)) { @@ -226,6 +245,116 @@ public class GuiHandler extends EventRegistrations { 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 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 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 buttonList) { boolean isCustomMainMenuMod = guiScreen.getClass().getName().endsWith("custommainmenu.gui.GuiFakeMain"); MainMenuButtonPosition buttonPosition = MainMenuButtonPosition.valueOf(mod.getCore().getSettingsRegistry().get(Setting.MAIN_MENU_BUTTON)); @@ -280,6 +409,7 @@ public class GuiHandler extends EventRegistrations { 200, 20, "replaymod.gui.replayviewer", + null, this::onButton ); //#if FABRIC<=0 @@ -356,6 +486,27 @@ public class GuiHandler extends EventRegistrations { } } + private int determineButtonIndex(Collection 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 private void onButton(InjectedButton button) { Screen guiScreen = button.guiScreen; @@ -396,6 +547,7 @@ public class GuiHandler extends EventRegistrations { public final int id; private Consumer onClick; public InjectedButton(Screen guiScreen, int buttonId, int x, int y, int width, int height, String buttonText, + String tooltip, //#if MC>=11400 Consumer onClick //#else @@ -418,6 +570,11 @@ public class GuiHandler extends EventRegistrations { //#if MC>=11400 , self -> onClick.accept((InjectedButton) self) //#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 //$$ , DEFAULT_NARRATION_SUPPLIER //#endif @@ -429,6 +586,12 @@ public class GuiHandler extends EventRegistrations { //#else //$$ this.onClick = null; //#endif + + //#if MC>=11903 + //$$ if (tooltip != null) { + //$$ setTooltip(Tooltip.of(Text.translatable(tooltip))); + //$$ } + //#endif } //#if MC>=11400 && MC<11400