Merge branch '1.11.2-dev' into 1.12-dev

This commit is contained in:
Jonas Herzig
2018-01-17 00:18:04 +01:00
65 changed files with 2237 additions and 67 deletions

View File

@@ -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

View 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);
}

View File

@@ -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);
}
}
}

View File

@@ -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.");
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}
}