Files
ReplayModCinematic/src/main/java/com/replaymod/replay/handler/GuiHandler.java
2019-07-19 14:25:42 +02:00

287 lines
10 KiB
Java

package com.replaymod.replay.handler;
import de.johni0702.minecraft.gui.utils.EventRegistrations;
import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.gui.screen.GuiReplayViewer;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.screen.GameMenuScreen;
import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.resource.language.I18n;
//#if MC>=11400
import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
//#else
//$$ import net.minecraftforge.client.event.GuiScreenEvent;
//$$ import net.minecraftforge.eventbus.api.SubscribeEvent;
//#endif
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import static com.replaymod.core.versions.MCVer.*;
import static com.replaymod.replay.ReplayModReplay.LOGGER;
public class GuiHandler extends EventRegistrations {
private static final int BUTTON_REPLAY_VIEWER = 17890234;
private static final int BUTTON_EXIT_REPLAY = 17890235;
private final ReplayModReplay mod;
public GuiHandler(ReplayModReplay mod) {
this.mod = mod;
}
//#if MC>=11400
{ on(InitScreenCallback.EVENT, this::injectIntoIngameMenu); }
private void injectIntoIngameMenu(Screen guiScreen, List<AbstractButtonWidget> buttonList) {
//#else
//$$ @SubscribeEvent
//$$ public void injectIntoIngameMenu(GuiScreenEvent.InitGuiEvent.Post event) {
//$$ GuiScreen guiScreen = getGui(event);
//$$ List<GuiButton> buttonList = getButtonList(event);
//#endif
if (!(guiScreen instanceof GameMenuScreen)) {
return;
}
if (mod.getReplayHandler() != null) {
// Pause replay when menu is opened
mod.getReplayHandler().getReplaySender().setReplaySpeed(0);
//#if MC>=11400
final String BUTTON_OPTIONS = I18n.translate("menu.options");
final String BUTTON_EXIT_SERVER = I18n.translate("menu.disconnect");
final String BUTTON_ADVANCEMENTS = I18n.translate("gui.advancements");
final String BUTTON_STATS = I18n.translate("gui.stats");
final String BUTTON_OPEN_TO_LAN = I18n.translate("menu.shareToLan");
//#else
//#if MC>=11300
//$$ final int BUTTON_OPTIONS = 0;
//#endif
//$$ final int BUTTON_EXIT_SERVER = 1;
//$$ final int BUTTON_ADVANCEMENTS = 5;
//$$ final int BUTTON_STATS = 6;
//$$ final int BUTTON_OPEN_TO_LAN = 7;
//#endif
//#if MC<11300
//$$ GuiButton openToLan = null;
//#endif
//#if MC>=11400
AbstractButtonWidget achievements = null, stats = null;
for(AbstractButtonWidget b : new ArrayList<>(buttonList)) {
//#else
//$$ GuiButton achievements = null, stats = null;
//$$ for(GuiButton b : new ArrayList<>(buttonList)) {
//#endif
boolean remove = false;
//#if MC>=11400
String id = b.getMessage();
//#else
//$$ Integer id = b.id;
//#endif
if (id.equals(BUTTON_EXIT_SERVER)) {
// Replace "Exit Server" button with "Exit Replay" button
remove = true;
addButton(guiScreen, new InjectedButton(
guiScreen,
BUTTON_EXIT_REPLAY,
b.x,
b.y,
width(b),
height(b),
I18n.translate("replaymod.gui.exit"),
this::onButton
));
} else if (id.equals(BUTTON_ADVANCEMENTS)) {
// Remove "Advancements", "Stats" and "Open to LAN" buttons
remove = true;
achievements = b;
} else if (id.equals(BUTTON_STATS)) {
remove = true;
stats = b;
} else if (id.equals(BUTTON_OPEN_TO_LAN)) {
remove = true;
//#if MC<11300
//$$ openToLan = b;
//#endif
//#if MC>=11300
} else if (id.equals(BUTTON_OPTIONS)) {
//#if MC>=11400
width(b, 204);
//#else
//$$ width(b, 200);
//#endif
//#endif
}
if (remove) {
// Moving the button far off-screen is easier to do cross-version than actually removing it
b.x = -1000;
b.y = -1000;
}
}
if (achievements != null && stats != null) {
moveAllButtonsDirectlyBelowUpwards(buttonList, achievements.y,
achievements.x, stats.x + width(stats));
}
// In 1.13+ Forge, the Options button shares one row with the Open to LAN button
//#if MC<11300
//$$ if (openToLan != null) {
//$$ moveAllButtonsDirectlyBelowUpwards(buttonList, openToLan.y,
//$$ openToLan.x, openToLan.x + openToLan.width);
//$$ }
//#endif
}
}
/**
* Moves all buttons that are within a rectangle below a certain y coordinate upwards by 24 units.
* @param buttons List of buttons
* @param belowY The Y limit
* @param xStart Left x limit of the rectangle
* @param xEnd Right x limit of the rectangle
*/
private void moveAllButtonsDirectlyBelowUpwards(
//#if MC>=11400
List<AbstractButtonWidget> buttons,
//#else
//$$ List<GuiButton> buttons,
//#endif
int belowY,
int xStart,
int xEnd
) {
buttons.stream()
.filter(button -> button.y >= belowY)
.filter(button -> button.x <= xEnd && button.x + width(button) >= xStart)
.forEach(button -> button.y -= 24);
}
//#if MC>=11400
{ on(InitScreenCallback.EVENT, this::ensureReplayStopped); }
private void ensureReplayStopped(Screen guiScreen, List<AbstractButtonWidget> buttonList) {
//#else
//$$ @SubscribeEvent
//$$ public void ensureReplayStopped(GuiScreenEvent.InitGuiEvent event) {
//$$ GuiScreen guiScreen = getGui(event);
//#endif
if (!(guiScreen instanceof TitleScreen || guiScreen instanceof MultiplayerScreen)) {
return;
}
if (mod.getReplayHandler() != null) {
// Something went terribly wrong and we ended up in the main menu with the replay still active.
// To prevent players from joining live servers and using the CameraEntity, try to stop the replay now.
try {
mod.getReplayHandler().endReplay();
} catch (IOException e) {
LOGGER.error("Trying to stop broken replay: ", e);
} finally {
if (mod.getReplayHandler() != null) {
mod.forcefullyStopReplay();
}
}
}
}
//#if MC>=11400
{ on(InitScreenCallback.EVENT, this::injectIntoMainMenu); }
private void injectIntoMainMenu(Screen guiScreen, List<AbstractButtonWidget> buttonList) {
//#else
//$$ @SubscribeEvent
//$$ public void injectIntoMainMenu(GuiScreenEvent.InitGuiEvent event) {
//$$ GuiScreen guiScreen = getGui(event);
//#endif
if (!(guiScreen instanceof TitleScreen)) {
return;
}
ButtonWidget button = new InjectedButton(
guiScreen,
BUTTON_REPLAY_VIEWER,
guiScreen.width / 2 - 100,
guiScreen.height / 4 + 10 + 4 * 24,
98,
20,
I18n.translate("replaymod.gui.replayviewer"),
this::onButton
);
addButton(guiScreen, button);
}
//#if MC>=11300
private void onButton(InjectedButton button) {
Screen guiScreen = button.guiScreen;
//#else
//$$ @SubscribeEvent
//$$ public void onButton(GuiScreenEvent.ActionPerformedEvent.Pre event) {
//$$ GuiScreen guiScreen = getGui(event);
//$$ GuiButton button = getButton(event);
//#endif
if(!button.active) return;
if (guiScreen instanceof TitleScreen) {
if (button.id == BUTTON_REPLAY_VIEWER) {
new GuiReplayViewer(mod).display();
}
}
if (guiScreen instanceof GameMenuScreen && mod.getReplayHandler() != null) {
if (button.id == BUTTON_EXIT_REPLAY) {
button.active = false;
try {
mod.getReplayHandler().endReplay();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static class InjectedButton extends ButtonWidget {
public final Screen guiScreen;
public final int id;
private Consumer<InjectedButton> onClick;
public InjectedButton(Screen guiScreen, int buttonId, int x, int y, int width, int height, String buttonText,
//#if MC>=11300
Consumer<InjectedButton> onClick
//#else
//$$ Consumer<GuiScreenEvent.ActionPerformedEvent.Pre> onClick
//#endif
) {
super(
//#if MC<11400
//$$ buttonId,
//#endif
x,
y,
width,
height,
buttonText
//#if MC>=11400
, self -> onClick.accept((InjectedButton) self)
//#endif
);
this.guiScreen = guiScreen;
this.id = buttonId;
//#if MC>=11300
this.onClick = onClick;
//#else
//$$ this.onClick = null;
//#endif
}
//#if MC>=11300 && MC<11400
//$$ @Override
//$$ public void onClick(double mouseX, double mouseY) {
//$$ onClick.accept(this);
//$$ }
//#endif
}
}