Merge branch '1.8.9-dev' into 1.9.4-dev
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.replaymod.extras;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.extras.advancedscreenshots.AdvancedScreenshots;
|
||||
import com.replaymod.extras.playeroverview.PlayerOverview;
|
||||
import com.replaymod.extras.urischeme.UriSchemeExtra;
|
||||
import com.replaymod.extras.youtube.YoutubeUpload;
|
||||
@@ -19,6 +20,7 @@ import java.util.Optional;
|
||||
version = "@MOD_VERSION@",
|
||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||
acceptableRemoteVersions = "*",
|
||||
clientSideOnly = true,
|
||||
useMetadata = true)
|
||||
public class ReplayModExtras {
|
||||
public static final String MOD_ID = "replaymod-extras";
|
||||
@@ -27,6 +29,7 @@ public class ReplayModExtras {
|
||||
public static ReplayModExtras instance;
|
||||
|
||||
private static final List<Class<? extends Extra>> builtin = Arrays.asList(
|
||||
AdvancedScreenshots.class,
|
||||
PlayerOverview.class,
|
||||
UriSchemeExtra.class,
|
||||
YoutubeUpload.class,
|
||||
@@ -43,6 +46,7 @@ public class ReplayModExtras {
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
LOGGER = event.getModLog();
|
||||
ReplayMod.instance.getSettingsRegistry().register(Setting.class);
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
|
||||
8
src/main/java/com/replaymod/extras/Setting.java
Normal file
8
src/main/java/com/replaymod/extras/Setting.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.replaymod.extras;
|
||||
|
||||
import com.replaymod.core.SettingsRegistry;
|
||||
|
||||
public final class Setting<T> {
|
||||
public static final SettingsRegistry.SettingKey<Boolean> SKIP_POST_SCREENSHOT_GUI =
|
||||
new SettingsRegistry.SettingKeys<>("advanced", "skipPostScreenshotGui", null, false);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.replaymod.extras.advancedscreenshots;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.extras.Extra;
|
||||
import com.replaymod.replay.events.ReplayDispatchKeypressesEvent;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiControls;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
public class AdvancedScreenshots implements Extra {
|
||||
|
||||
private ReplayMod mod;
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
@Override
|
||||
public void register(ReplayMod mod) throws Exception {
|
||||
this.mod = mod;
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onDispatchKeypresses(ReplayDispatchKeypressesEvent.Pre event) {
|
||||
int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() : Keyboard.getEventKey();
|
||||
|
||||
// all the conditions required to trigger a screenshot condensed in a single if statement
|
||||
if (keyCode != 0 && !Keyboard.isRepeatEvent()
|
||||
&& (!(mc.currentScreen instanceof GuiControls) || ((GuiControls) mc.currentScreen).time <= mc.getSystemTime() - 20L)
|
||||
&& Keyboard.getEventKeyState()
|
||||
&& keyCode == mc.gameSettings.keyBindScreenshot.getKeyCode()) {
|
||||
|
||||
ReplayMod.instance.runLater(() -> {
|
||||
new GuiCreateScreenshot(mod).display();
|
||||
});
|
||||
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.replaymod.extras.advancedscreenshots;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import com.replaymod.render.gui.GuiRenderSettings;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||
import de.johni0702.minecraft.gui.function.Loadable;
|
||||
import de.johni0702.minecraft.gui.layout.GridLayout;
|
||||
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.util.ScreenShotHelper;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.common.config.Property;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.replaymod.core.utils.Utils.error;
|
||||
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||
|
||||
public class GuiCreateScreenshot extends GuiRenderSettings implements Loadable {
|
||||
|
||||
private final ReplayMod mod;
|
||||
|
||||
public GuiCreateScreenshot(ReplayMod mod) {
|
||||
super(null, null);
|
||||
|
||||
this.mod = mod;
|
||||
|
||||
resetChildren(settingsList.getListPanel()).addElements(new VerticalLayout.Data(0.5),
|
||||
new GuiLabel().setI18nText("replaymod.gui.advancedscreenshots.title"), mainPanel, new GuiPanel(),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.advanced"), advancedPanel, new GuiPanel());
|
||||
|
||||
resetChildren(mainPanel).addElements(new GridLayout.Data(1, 0.5),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.renderer"), renderMethodDropdown,
|
||||
new GuiLabel().setI18nText("replaymod.gui.advancedscreenshots.resolution"), videoResolutionPanel,
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.outputfile"), outputFileButton);
|
||||
|
||||
resetChildren(advancedPanel).addElements(null, nametagCheckbox, new GuiPanel().setLayout(
|
||||
new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(15))
|
||||
.addElements(new GridLayout.Data(0, 0.5),
|
||||
new GuiLabel().setI18nText("replaymod.gui.rendersettings.stabilizecamera"), stabilizePanel,
|
||||
chromaKeyingCheckbox, chromaKeyingColor));
|
||||
|
||||
exportArguments.setText(""); // To disable any preset-based checks
|
||||
buttonPanel.removeElement(queueButton);
|
||||
renderButton.setI18nLabel("replaymod.gui.advancedscreenshots.create").onClick(() -> {
|
||||
// Closing this GUI ensures that settings are saved
|
||||
getMinecraft().displayGuiScreen(null);
|
||||
|
||||
mod.runLater(() -> {
|
||||
try {
|
||||
RenderSettings settings = save(false);
|
||||
|
||||
boolean success = new ScreenshotRenderer(settings).renderScreenshot();
|
||||
if (success) {
|
||||
new GuiUploadScreenshot(ReplayModReplay.instance.getReplayHandler().getOverlay(), mod,
|
||||
settings).open();
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
error(LOGGER, GuiCreateScreenshot.this, CrashReport.makeCrashReport(t, "Rendering video"), () -> {});
|
||||
display(); // Re-show the render settings gui and the new error popup
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private <T extends GuiContainer<?>> T resetChildren(T container) {
|
||||
new ArrayList<>(container.getChildren()).forEach(container::removeElement);
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// pause replay when opening this gui
|
||||
ReplayModReplay.instance.getReplayHandler().getReplaySender().setReplaySpeed(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File generateOutputFile(RenderSettings.EncodingPreset encodingPreset) {
|
||||
File screenshotFolder = new File(getMinecraft().mcDataDir, "screenshots");
|
||||
return ScreenShotHelper.getTimestampedPNGFileForDirectory(screenshotFolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Property getConfigProperty(Configuration configuration) {
|
||||
return configuration.get("screenshotsettings", "settings", "{}",
|
||||
"Last state of the screenshot settings GUI. Internal use only.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.replaymod.extras.advancedscreenshots;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.SettingsRegistry;
|
||||
import com.replaymod.extras.Setting;
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||
import de.johni0702.minecraft.gui.element.GuiButton;
|
||||
import de.johni0702.minecraft.gui.element.GuiCheckbox;
|
||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
|
||||
import org.lwjgl.util.ReadableColor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
public class GuiUploadScreenshot extends AbstractGuiPopup<GuiUploadScreenshot> {
|
||||
|
||||
public final ReplayMod mod;
|
||||
|
||||
public final RenderSettings renderSettings;
|
||||
|
||||
public final GuiLabel successLabel = new GuiLabel()
|
||||
.setI18nText("replaymod.gui.advancedscreenshots.finished.description")
|
||||
.setColor(ReadableColor.BLACK);
|
||||
|
||||
public final GuiLabel veerLabel = new GuiLabel()
|
||||
.setI18nText("replaymod.gui.advancedscreenshots.finished.description.veer")
|
||||
.setColor(ReadableColor.BLACK);
|
||||
|
||||
public final GuiButton veerUploadButton = new GuiButton()
|
||||
.setSize(150, 20)
|
||||
.setI18nLabel("replaymod.gui.advancedscreenshots.finished.upload.veer");
|
||||
|
||||
public final GuiButton showOnDiskButton = new GuiButton()
|
||||
.setSize(150, 20)
|
||||
.setI18nLabel("replaymod.gui.advancedscreenshots.finished.showfile");
|
||||
|
||||
public final GuiButton closeButton = new GuiButton()
|
||||
.setSize(150, 20)
|
||||
.setI18nLabel("replaymod.gui.close");
|
||||
|
||||
public final GuiCheckbox neverOpenCheckbox = new GuiCheckbox();
|
||||
|
||||
public final GuiLabel neverOpenLabel = new GuiLabel()
|
||||
.setI18nText("replaymod.gui.notagain")
|
||||
.setColor(ReadableColor.BLACK);
|
||||
|
||||
public final GuiPanel checkboxPanel = GuiPanel.builder()
|
||||
.layout(new HorizontalLayout(HorizontalLayout.Alignment.RIGHT).setSpacing(5))
|
||||
.with(neverOpenCheckbox, new HorizontalLayout.Data(0.5))
|
||||
.with(neverOpenLabel, new HorizontalLayout.Data(0.5))
|
||||
.build();
|
||||
|
||||
public GuiUploadScreenshot(GuiContainer container, ReplayMod mod, RenderSettings renderSettings) {
|
||||
super(container);
|
||||
this.mod = mod;
|
||||
this.renderSettings = renderSettings;
|
||||
|
||||
boolean veer = renderSettings.getRenderMethod() == RenderSettings.RenderMethod.EQUIRECTANGULAR;
|
||||
|
||||
if (renderSettings.getRenderMethod() == RenderSettings.RenderMethod.EQUIRECTANGULAR) {
|
||||
successLabel.setI18nText("replaymod.gui.advancedscreenshots.finished.description.360");
|
||||
}
|
||||
|
||||
if (veer) {
|
||||
veerUploadButton.onClick(() -> {
|
||||
try {
|
||||
Desktop.getDesktop().browse(URI.create("https://veer.tv/upload"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showOnDiskButton.onClick(() -> {
|
||||
try {
|
||||
Desktop.getDesktop().browse(renderSettings.getOutputFile().toURI());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
closeButton.onClick(() -> {
|
||||
if (neverOpenCheckbox.isChecked()) {
|
||||
SettingsRegistry settingsRegistry = mod.getSettingsRegistry();
|
||||
settingsRegistry.set(Setting.SKIP_POST_SCREENSHOT_GUI, true);
|
||||
settingsRegistry.save();
|
||||
}
|
||||
close();
|
||||
});
|
||||
|
||||
popup.addElements(new VerticalLayout.Data(0.5), successLabel);
|
||||
|
||||
if (veer) {
|
||||
popup.addElements(new VerticalLayout.Data(0.5),
|
||||
veerLabel,
|
||||
veerUploadButton);
|
||||
}
|
||||
|
||||
popup.addElements(new VerticalLayout.Data(0.5),
|
||||
successLabel,
|
||||
showOnDiskButton,
|
||||
closeButton);
|
||||
|
||||
popup.addElements(new VerticalLayout.Data(1),
|
||||
checkboxPanel);
|
||||
|
||||
popup.setLayout(new VerticalLayout().setSpacing(5));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void open() {
|
||||
if (mod.getSettingsRegistry().get(Setting.SKIP_POST_SCREENSHOT_GUI)) {
|
||||
return;
|
||||
}
|
||||
super.open();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GuiUploadScreenshot getThis() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.replaymod.extras.advancedscreenshots;
|
||||
|
||||
import com.replaymod.render.RenderSettings;
|
||||
import com.replaymod.render.capturer.RenderInfo;
|
||||
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
|
||||
import com.replaymod.render.rendering.Pipelines;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import org.lwjgl.util.Dimension;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ScreenshotRenderer implements RenderInfo {
|
||||
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private final RenderSettings settings;
|
||||
|
||||
public boolean renderScreenshot() throws Throwable {
|
||||
try {
|
||||
int displayWidthBefore = mc.displayWidth;
|
||||
int displayHeightBefore = mc.displayHeight;
|
||||
|
||||
boolean hideGUIBefore = mc.gameSettings.hideGUI;
|
||||
mc.gameSettings.hideGUI = true;
|
||||
|
||||
ChunkLoadingRenderGlobal clrg = new ChunkLoadingRenderGlobal(mc.renderGlobal);
|
||||
|
||||
Pipelines.newPipeline(settings.getRenderMethod(),this,
|
||||
new ScreenshotWriter(settings.getOutputFile())).run();
|
||||
|
||||
clrg.uninstall();
|
||||
|
||||
mc.gameSettings.hideGUI = hideGUIBefore;
|
||||
mc.resize(displayWidthBefore, displayHeightBefore);
|
||||
return true;
|
||||
} catch (OutOfMemoryError e) {
|
||||
e.printStackTrace();
|
||||
CrashReport report = CrashReport.makeCrashReport(e, "Creating Equirectangular Screenshot");
|
||||
Minecraft.getMinecraft().crashed(report);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableDimension getFrameSize() {
|
||||
return new Dimension(settings.getVideoWidth(), settings.getVideoHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalFrames() {
|
||||
// render 2 frames, because only the second contains all frames fully loaded
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float updateForNextFrame() {
|
||||
return mc.timer.renderPartialTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderSettings getRenderSettings() {
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.replaymod.extras.advancedscreenshots;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.utils.Utils;
|
||||
import com.replaymod.extras.ReplayModExtras;
|
||||
import com.replaymod.render.frame.RGBFrame;
|
||||
import com.replaymod.render.rendering.FrameConsumer;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ScreenshotWriter implements FrameConsumer<RGBFrame> {
|
||||
|
||||
private final File outputFile;
|
||||
|
||||
public ScreenshotWriter(File outputFile) {
|
||||
this.outputFile = outputFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(RGBFrame frame) {
|
||||
// skip the first frame, in which not all chunks are properly loaded
|
||||
if (frame.getFrameId() == 0) return;
|
||||
|
||||
try {
|
||||
final ReadableDimension frameSize = frame.getSize();
|
||||
|
||||
BufferedImage img = new BufferedImage(frameSize.getWidth(), frameSize.getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||
for (int y = 0; y < frameSize.getHeight(); y++) {
|
||||
for (int x = 0; x < frameSize.getWidth(); x++) {
|
||||
byte r = frame.getByteBuffer().get();
|
||||
byte g = frame.getByteBuffer().get();
|
||||
byte b = frame.getByteBuffer().get();
|
||||
|
||||
int color = ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
|
||||
img.setRGB(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
outputFile.getParentFile().mkdirs();
|
||||
ImageIO.write(img, "PNG", outputFile);
|
||||
} catch (OutOfMemoryError e) {
|
||||
e.printStackTrace();
|
||||
CrashReport report = CrashReport.makeCrashReport(e, "Exporting frame");
|
||||
Minecraft.getMinecraft().crashed(report);
|
||||
} catch (Throwable t) {
|
||||
CrashReport report = CrashReport.makeCrashReport(t, "Exporting frame");
|
||||
|
||||
ReplayMod.instance.runLater(() -> Utils.error(ReplayModExtras.LOGGER,
|
||||
ReplayModReplay.instance.getReplayHandler().getOverlay(),
|
||||
report, null));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user