Add configurable, small Replay Viewer button (closes #471)
This commit is contained in:
@@ -199,6 +199,12 @@ repositories {
|
||||
name = "fabric"
|
||||
url = "https://maven.fabricmc.net/"
|
||||
}
|
||||
maven {
|
||||
url 'https://maven.terraformersmc.com/releases/'
|
||||
content {
|
||||
includeGroup 'com.terraformersmc'
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
content {
|
||||
@@ -323,8 +329,7 @@ dependencies {
|
||||
|
||||
if (FABRIC) {
|
||||
if (mcVersion >= 11602) {
|
||||
// TODO re-add to runtime once available
|
||||
modCompileOnly 'io.github.prospector:modmenu:1.14.0+build.24'
|
||||
modCompile 'com.terraformersmc:modmenu:1.16.8'
|
||||
} else if (mcVersion >= 11600) {
|
||||
modCompile 'io.github.prospector:modmenu:1.14.0+build.24'
|
||||
} else {
|
||||
|
||||
@@ -223,6 +223,12 @@ public class MCVer {
|
||||
if (message.equals(b.getMessage())) {
|
||||
return Optional.of(b);
|
||||
}
|
||||
//#if MC>=11600
|
||||
// Fuzzy match (copy does not include children)
|
||||
if (b.getMessage() != null && b.getMessage().copy().equals(message)) {
|
||||
return Optional.of(b);
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package com.replaymod.replay;
|
||||
|
||||
import com.replaymod.core.SettingsRegistry;
|
||||
import com.replaymod.replay.handler.GuiHandler.MainMenuButtonPosition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
|
||||
public static final Setting<Boolean> SHOW_CHAT = make("showChat", "showchat", true);
|
||||
@@ -8,6 +12,12 @@ public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
|
||||
public static final SettingsRegistry.MultipleChoiceSettingKeys<String> CAMERA =
|
||||
new SettingsRegistry.MultipleChoiceSettingKeys<>(
|
||||
"replay", "camera", "replaymod.gui.settings.camera", "replaymod.camera.classic");
|
||||
public static final SettingsRegistry.MultipleChoiceSettingKeys<String> MAIN_MENU_BUTTON =
|
||||
new SettingsRegistry.MultipleChoiceSettingKeys<>(
|
||||
"replay", "mainMenuButton", null, MainMenuButtonPosition.DEFAULT.name());
|
||||
static {
|
||||
MAIN_MENU_BUTTON.setChoices(Arrays.stream(MainMenuButtonPosition.values()).map(Enum::name).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private static <T> Setting<T> make(String key, String displayName, T defaultValue) {
|
||||
return new Setting<>(key, displayName, defaultValue);
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package com.replaymod.replay.handler;
|
||||
|
||||
import com.replaymod.core.gui.GuiReplayButton;
|
||||
import com.replaymod.replay.Setting;
|
||||
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
|
||||
import de.johni0702.minecraft.gui.element.GuiTooltip;
|
||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
||||
import de.johni0702.minecraft.gui.utils.lwjgl.Point;
|
||||
import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import com.replaymod.replay.gui.screen.GuiReplayViewer;
|
||||
@@ -28,9 +34,11 @@ import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.replaymod.core.versions.MCVer.*;
|
||||
import static com.replaymod.replay.ReplayModReplay.LOGGER;
|
||||
@@ -217,6 +225,34 @@ public class GuiHandler extends EventRegistrations {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isCustomMainMenuMod = guiScreen.getClass().getName().endsWith("custommainmenu.gui.GuiFakeMain");
|
||||
|
||||
MainMenuButtonPosition buttonPosition = MainMenuButtonPosition.valueOf(mod.getCore().getSettingsRegistry().get(Setting.MAIN_MENU_BUTTON));
|
||||
if (buttonPosition != MainMenuButtonPosition.BIG && !isCustomMainMenuMod) {
|
||||
VanillaGuiScreen vanillaGui = VanillaGuiScreen.wrap(guiScreen);
|
||||
|
||||
GuiReplayButton replayButton = new GuiReplayButton();
|
||||
replayButton
|
||||
.onClick(() -> new GuiReplayViewer(mod).display())
|
||||
.setTooltip(new GuiTooltip().setI18nText("replaymod.gui.replayviewer"));
|
||||
|
||||
vanillaGui.setLayout(new CustomLayout<de.johni0702.minecraft.gui.container.GuiScreen>(vanillaGui.getLayout()) {
|
||||
private Point pos;
|
||||
|
||||
@Override
|
||||
protected void layout(de.johni0702.minecraft.gui.container.GuiScreen container, int width, int height) {
|
||||
if (pos == null) {
|
||||
// Delaying computation so we can take into account buttons
|
||||
// added after our callback.
|
||||
pos = determineButtonPos(buttonPosition, guiScreen, buttonList);
|
||||
}
|
||||
size(replayButton, 20, 20);
|
||||
pos(replayButton, pos.getX(), pos.getY());
|
||||
}
|
||||
}).addElements(null, replayButton);
|
||||
return;
|
||||
}
|
||||
|
||||
int x = guiScreen.width / 2 - 100;
|
||||
// We want to position our button below the realms button
|
||||
int y = findButton(buttonList, "menu.online", 14)
|
||||
@@ -246,7 +282,7 @@ public class GuiHandler extends EventRegistrations {
|
||||
this::onButton
|
||||
);
|
||||
//#if FABRIC<=0
|
||||
//$$ if (guiScreen.getClass().getName().endsWith("custommainmenu.gui.GuiFakeMain")) {
|
||||
//$$ if (isCustomMainMenuMod) {
|
||||
//$$ // CustomMainMenu uses a different list in the event than in its Fake gui
|
||||
//$$ buttonList.add(button);
|
||||
//$$ return;
|
||||
@@ -255,6 +291,70 @@ public class GuiHandler extends EventRegistrations {
|
||||
addButton(guiScreen, button);
|
||||
}
|
||||
|
||||
private Point determineButtonPos(MainMenuButtonPosition buttonPosition, Screen guiScreen, List<AbstractButtonWidget> buttonList) {
|
||||
Point topRight = new Point(guiScreen.width - 20 - 5, 5);
|
||||
|
||||
if (buttonPosition == MainMenuButtonPosition.TOP_LEFT) {
|
||||
return new Point(5, 5);
|
||||
} else if (buttonPosition == MainMenuButtonPosition.TOP_RIGHT) {
|
||||
return topRight;
|
||||
} else if (buttonPosition == MainMenuButtonPosition.DEFAULT) {
|
||||
return Stream.of(
|
||||
findButton(buttonList, "menu.singleplayer", 1),
|
||||
findButton(buttonList, "menu.multiplayer", 2),
|
||||
findButton(buttonList, "menu.online", 14),
|
||||
findButton(buttonList, "modmenu.title", 6)
|
||||
)
|
||||
// skip buttons which do not exist
|
||||
.flatMap(it -> it.map(Stream::of).orElseGet(Stream::empty))
|
||||
// skip buttons which already have something next to them
|
||||
.filter(it -> buttonList.stream().noneMatch(button ->
|
||||
button.x <= it.x + it.getWidth() + 4 + 20
|
||||
&& button.y <= it.y + it.getHeight()
|
||||
&& button.x + button.getWidth() >= it.x + it.getWidth() + 4
|
||||
&& button.y + button.getHeight() >= it.y
|
||||
))
|
||||
// then take the bottom-most and if there's two, the right-most
|
||||
.max(Comparator.<AbstractButtonWidget>comparingInt(it -> it.y).thenComparingInt(it -> it.x))
|
||||
// and place ourselves next to it
|
||||
.map(it -> new Point(it.x + it.getWidth() + 4, it.y))
|
||||
// if all fails, just go with TOP_RIGHT
|
||||
.orElse(topRight);
|
||||
} else {
|
||||
return Optional.of(buttonList).flatMap(buttons -> {
|
||||
switch (buttonPosition) {
|
||||
case LEFT_OF_SINGLEPLAYER:
|
||||
case RIGHT_OF_SINGLEPLAYER:
|
||||
return findButton(buttons, "menu.singleplayer", 1);
|
||||
case LEFT_OF_MULTIPLAYER:
|
||||
case RIGHT_OF_MULTIPLAYER:
|
||||
return findButton(buttons, "menu.multiplayer", 2);
|
||||
case LEFT_OF_REALMS:
|
||||
case RIGHT_OF_REALMS:
|
||||
return findButton(buttons, "menu.online", 14);
|
||||
case LEFT_OF_MODS:
|
||||
case RIGHT_OF_MODS:
|
||||
return findButton(buttons, "modmenu.title", 6);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}).map(button -> {
|
||||
switch (buttonPosition) {
|
||||
case LEFT_OF_SINGLEPLAYER:
|
||||
case LEFT_OF_MULTIPLAYER:
|
||||
case LEFT_OF_REALMS:
|
||||
case LEFT_OF_MODS:
|
||||
return new Point(button.x - 4 - 20, button.y);
|
||||
case RIGHT_OF_MODS:
|
||||
case RIGHT_OF_SINGLEPLAYER:
|
||||
case RIGHT_OF_MULTIPLAYER:
|
||||
case RIGHT_OF_REALMS:
|
||||
return new Point(button.x + button.getWidth() + 4, button.y);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}).orElse(topRight);
|
||||
}
|
||||
}
|
||||
|
||||
//#if MC>=11400
|
||||
private void onButton(InjectedButton button) {
|
||||
Screen guiScreen = button.guiScreen;
|
||||
@@ -334,4 +434,22 @@ public class GuiHandler extends EventRegistrations {
|
||||
//$$ }
|
||||
//#endif
|
||||
}
|
||||
|
||||
public enum MainMenuButtonPosition {
|
||||
// The old big button below Realms/Mods which pushes other buttons around.
|
||||
BIG,
|
||||
// Right of the bottom-most button in the main block of buttons (so not the quit button).
|
||||
// That will generally be either RIGHT_OF_REALMS or RIGHT_OF_MODS depending on version and installed mods.
|
||||
DEFAULT,
|
||||
TOP_LEFT,
|
||||
TOP_RIGHT,
|
||||
LEFT_OF_SINGLEPLAYER,
|
||||
RIGHT_OF_SINGLEPLAYER,
|
||||
LEFT_OF_MULTIPLAYER,
|
||||
RIGHT_OF_MULTIPLAYER,
|
||||
LEFT_OF_REALMS,
|
||||
RIGHT_OF_REALMS,
|
||||
LEFT_OF_MODS,
|
||||
RIGHT_OF_MODS,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
//#if MC>=11600
|
||||
package com.replaymod.replay.mixin;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.replay.Setting;
|
||||
import com.replaymod.replay.handler.GuiHandler.MainMenuButtonPosition;
|
||||
import net.minecraft.client.gui.screen.TitleScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -14,7 +17,11 @@ public abstract class Mixin_MoveRealmsButton {
|
||||
index = 2
|
||||
)
|
||||
private int adjustRealmsButton(int height) {
|
||||
return height - 24 * 4;
|
||||
String setting = ReplayMod.instance.getSettingsRegistry().get(Setting.MAIN_MENU_BUTTON);
|
||||
if (MainMenuButtonPosition.valueOf(setting) == MainMenuButtonPosition.BIG) {
|
||||
height -= 24 * 4;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
Reference in New Issue
Block a user