Merge branch '1.8.9-dev' into 1.9.4-dev
This commit is contained in:
@@ -12,7 +12,7 @@ to access private fields is a good indication that this has happened).
|
|||||||
You can build the mod by running `./gradlew :build`. You can then find the final jar files in `build/libs/`.
|
You can build the mod by running `./gradlew :build`. You can then find the final jar files in `build/libs/`.
|
||||||
|
|
||||||
### IntelliJ
|
### IntelliJ
|
||||||
For the initial setup run `./gradlew preshadowJar idea genIntellijRuns`.
|
For the initial setup run `./gradlew idea genIntellijRuns`.
|
||||||
You also need to enable the Mixin annotation processor:
|
You also need to enable the Mixin annotation processor:
|
||||||
1. Go to File -> Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors
|
1. Go to File -> Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors
|
||||||
2. Tick "Enable annotation processing"
|
2. Tick "Enable annotation processing"
|
||||||
@@ -20,8 +20,8 @@ You also need to enable the Mixin annotation processor:
|
|||||||
4. Set the name to "reobfSrgFile" and the value to "$path/build/mcp-srg.srg" where you replace $path with the full
|
4. Set the name to "reobfSrgFile" and the value to "$path/build/mcp-srg.srg" where you replace $path with the full
|
||||||
path to the folder containing the gradlew file
|
path to the folder containing the gradlew file
|
||||||
|
|
||||||
Whenever you switch to another branch, you can either just run `./gradlew preshadowJar idea` or instead run
|
Whenever you switch to another branch, you can either just run `./gradlew idea` or instead run
|
||||||
`./gradlew preshadowJar copySrg` and then refresh the gradle project from within IntelliJ.
|
`./gradlew copySrg` and then refresh the gradle project from within IntelliJ.
|
||||||
|
|
||||||
### Eclipse
|
### Eclipse
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ dependencies {
|
|||||||
|
|
||||||
shade 'org.aspectj:aspectjrt:1.8.2'
|
shade 'org.aspectj:aspectjrt:1.8.2'
|
||||||
|
|
||||||
shade 'com.github.replaymod:ReplayStudio:c7ed696'
|
shade 'com.github.replaymod:ReplayStudio:14daa88'
|
||||||
|
|
||||||
testCompile 'junit:junit:4.11'
|
testCompile 'junit:junit:4.11'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ f98b3e07c6b6a32dd6f9f70f5cef4ac9be42a9a6c850ceb8f33767da94706635 /com/github/joh
|
|||||||
03e3dff7f9b3ac6cd3b87684fd36a2f6996a4b164a2f8fab9c22c01cb7bfb84b /com/github/johni0702/gradle-reproducible-builds-plugin/a524ada/gradle-reproducible-builds-plugin-a524ada.pom
|
03e3dff7f9b3ac6cd3b87684fd36a2f6996a4b164a2f8fab9c22c01cb7bfb84b /com/github/johni0702/gradle-reproducible-builds-plugin/a524ada/gradle-reproducible-builds-plugin-a524ada.pom
|
||||||
75ccc0e24d37ed5b8916e1bcffad1e067c2b1cfa21b635287f968db5c3c1963a /com/github/jponge/lzma-java/1.3/lzma-java-1.3.jar
|
75ccc0e24d37ed5b8916e1bcffad1e067c2b1cfa21b635287f968db5c3c1963a /com/github/jponge/lzma-java/1.3/lzma-java-1.3.jar
|
||||||
fbcba81b21a8bc3c0761e4798fa05285444b43d681c03c9af49f9b2e1ecb0184 /com/github/jponge/lzma-java/1.3/lzma-java-1.3.pom
|
fbcba81b21a8bc3c0761e4798fa05285444b43d681c03c9af49f9b2e1ecb0184 /com/github/jponge/lzma-java/1.3/lzma-java-1.3.pom
|
||||||
a37e00769fb00b8fdcfd939b92d1b7adbabebdc96e060991ee72053f5509439f /com/github/replaymod/ReplayStudio/c7ed696/ReplayStudio-c7ed696.jar
|
9de10955f2f5e43c982fab9c88b9fb5a7984e4be08f8665294920fa866dc38e2 /com/github/replaymod/ReplayStudio/14daa88/ReplayStudio-14daa88.jar
|
||||||
a98a18a476c0b4b861e86701f0442c90040dc7f086d097fe3adde0553cd217ad /com/github/replaymod/ReplayStudio/c7ed696/ReplayStudio-c7ed696.pom
|
2a48580e2a41a35303b5d661a8870f4adaefbd5216af1cbfcf3dd3ca1b906c61 /com/github/replaymod/ReplayStudio/14daa88/ReplayStudio-14daa88.pom
|
||||||
c6ebd74cd6108b8c372c95b842725ee5bd6d3303ba26cb00f18bc92f80b47956 /com/github/tony19/named-regexp/0.2.3/named-regexp-0.2.3.jar
|
c6ebd74cd6108b8c372c95b842725ee5bd6d3303ba26cb00f18bc92f80b47956 /com/github/tony19/named-regexp/0.2.3/named-regexp-0.2.3.jar
|
||||||
7cdd89a892927998beab59398ef073232588f6e83e411cf4f0905833bf300487 /com/github/tony19/named-regexp/0.2.3/named-regexp-0.2.3.pom
|
7cdd89a892927998beab59398ef073232588f6e83e411cf4f0905833bf300487 /com/github/tony19/named-regexp/0.2.3/named-regexp-0.2.3.pom
|
||||||
47c625c83a8cf97b8bbdff2acde923ff8fd3174e62aabcfc5d1b86692594ffba /com/google/api-client/google-api-client/1.22.0/google-api-client-1.22.0.jar
|
47c625c83a8cf97b8bbdff2acde923ff8fd3174e62aabcfc5d1b86692594ffba /com/google/api-client/google-api-client/1.22.0/google-api-client-1.22.0.jar
|
||||||
|
|||||||
2
jGui
2
jGui
Submodule jGui updated: e2bd90628e...b5fdbb85e1
@@ -7,16 +7,26 @@ import com.replaymod.compat.shaders.ShaderBeginRender;
|
|||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||||
import net.minecraftforge.fml.common.eventhandler.EventBus;
|
import net.minecraftforge.fml.common.eventhandler.EventBus;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@Mod(modid = ReplayModCompat.MOD_ID,
|
@Mod(modid = ReplayModCompat.MOD_ID,
|
||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModCompat {
|
public class ReplayModCompat {
|
||||||
public static final String MOD_ID = "replaymod-compat";
|
public static final String MOD_ID = "replaymod-compat";
|
||||||
|
|
||||||
|
public static Logger LOGGER;
|
||||||
|
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void preInit(FMLPreInitializationEvent event) {
|
||||||
|
LOGGER = event.getModLog();
|
||||||
|
}
|
||||||
|
|
||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
public void init(FMLInitializationEvent event) {
|
public void init(FMLInitializationEvent event) {
|
||||||
EventBus bus = MinecraftForge.EVENT_BUS;
|
EventBus bus = MinecraftForge.EVENT_BUS;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import net.minecraftforge.fml.common.versioning.VersionRange;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static com.replaymod.compat.ReplayModCompat.LOGGER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Old Better Sprinting versions replace the vanilla player with their own, overridden instance (replacing the camera entity).
|
* Old Better Sprinting versions replace the vanilla player with their own, overridden instance (replacing the camera entity).
|
||||||
*
|
*
|
||||||
@@ -34,7 +36,7 @@ public class DisableBetterSprinting {
|
|||||||
private static final VersionRange OLD_VERSION = VersionRange.newRange(null,
|
private static final VersionRange OLD_VERSION = VersionRange.newRange(null,
|
||||||
Collections.singletonList(new Restriction(null, false, new DefaultArtifactVersion("2.0.0"), false)));
|
Collections.singletonList(new Restriction(null, false, new DefaultArtifactVersion("2.0.0"), false)));
|
||||||
private static final String LOGIC_CLASS_NAME = "chylex.bettersprinting.client.player.impl.LogicImplOverride";
|
private static final String LOGIC_CLASS_NAME = "chylex.bettersprinting.client.player.impl.LogicImplOverride";
|
||||||
private static final String CONTROLLER_OVERRIDE_CLASS_NAME = LOGIC_CLASS_NAME + ".PlayerControllerMPOverride";
|
private static final String CONTROLLER_OVERRIDE_CLASS_NAME = LOGIC_CLASS_NAME + "$PlayerControllerMPOverride";
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
Loader.instance().getModList().stream()
|
Loader.instance().getModList().stream()
|
||||||
@@ -44,7 +46,9 @@ public class DisableBetterSprinting {
|
|||||||
.ifPresent($_ -> MinecraftForge.EVENT_BUS.register(new DisableBetterSprinting()));
|
.ifPresent($_ -> MinecraftForge.EVENT_BUS.register(new DisableBetterSprinting()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DisableBetterSprinting() {}
|
private DisableBetterSprinting() {
|
||||||
|
LOGGER.info("BetterSprinting workaround enabled");
|
||||||
|
}
|
||||||
|
|
||||||
private final Minecraft mc = Minecraft.getMinecraft();
|
private final Minecraft mc = Minecraft.getMinecraft();
|
||||||
private PlayerControllerMP originalController;
|
private PlayerControllerMP originalController;
|
||||||
@@ -71,6 +75,7 @@ public class DisableBetterSprinting {
|
|||||||
// Suppress this message if it's the Better Sprinting warning message
|
// Suppress this message if it's the Better Sprinting warning message
|
||||||
for (StackTraceElement elem : Thread.currentThread().getStackTrace()) {
|
for (StackTraceElement elem : Thread.currentThread().getStackTrace()) {
|
||||||
if (LOGIC_CLASS_NAME.equals(elem.getClassName())) {
|
if (LOGIC_CLASS_NAME.equals(elem.getClassName())) {
|
||||||
|
LOGGER.info("BetterSprinting warning message suppressed.");
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -83,6 +88,7 @@ public class DisableBetterSprinting {
|
|||||||
if (mc.playerController != null && mc.playerController.getClass().getName().equals(CONTROLLER_OVERRIDE_CLASS_NAME)) {
|
if (mc.playerController != null && mc.playerController.getClass().getName().equals(CONTROLLER_OVERRIDE_CLASS_NAME)) {
|
||||||
// Someone has secretly swapped out the player controller and is about to substitute their own player entity.
|
// Someone has secretly swapped out the player controller and is about to substitute their own player entity.
|
||||||
// This is the right time to destroy their plan.
|
// This is the right time to destroy their plan.
|
||||||
|
LOGGER.info("Preventing player controller {} from being replaced by BetterSprinting with {}.", originalController, mc.playerController);
|
||||||
mc.playerController = originalController;
|
mc.playerController = originalController;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import java.util.List;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
updateJSON = "https://raw.githubusercontent.com/ReplayMod/ReplayMod/master/versions.json",
|
updateJSON = "https://raw.githubusercontent.com/ReplayMod/ReplayMod/master/versions.json",
|
||||||
guiFactory = "com.replaymod.core.gui.GuiFactory")
|
guiFactory = "com.replaymod.core.gui.GuiFactory")
|
||||||
public class ReplayMod {
|
public class ReplayMod {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModEditor {
|
public class ReplayModEditor {
|
||||||
public static final String MOD_ID = "replaymod-editor";
|
public static final String MOD_ID = "replaymod-editor";
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.replaymod.extras;
|
package com.replaymod.extras;
|
||||||
|
|
||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.extras.advancedscreenshots.AdvancedScreenshots;
|
||||||
import com.replaymod.extras.playeroverview.PlayerOverview;
|
import com.replaymod.extras.playeroverview.PlayerOverview;
|
||||||
import com.replaymod.extras.urischeme.UriSchemeExtra;
|
import com.replaymod.extras.urischeme.UriSchemeExtra;
|
||||||
import com.replaymod.extras.youtube.YoutubeUpload;
|
import com.replaymod.extras.youtube.YoutubeUpload;
|
||||||
@@ -19,6 +20,7 @@ import java.util.Optional;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModExtras {
|
public class ReplayModExtras {
|
||||||
public static final String MOD_ID = "replaymod-extras";
|
public static final String MOD_ID = "replaymod-extras";
|
||||||
@@ -27,6 +29,7 @@ public class ReplayModExtras {
|
|||||||
public static ReplayModExtras instance;
|
public static ReplayModExtras instance;
|
||||||
|
|
||||||
private static final List<Class<? extends Extra>> builtin = Arrays.asList(
|
private static final List<Class<? extends Extra>> builtin = Arrays.asList(
|
||||||
|
AdvancedScreenshots.class,
|
||||||
PlayerOverview.class,
|
PlayerOverview.class,
|
||||||
UriSchemeExtra.class,
|
UriSchemeExtra.class,
|
||||||
YoutubeUpload.class,
|
YoutubeUpload.class,
|
||||||
@@ -43,6 +46,7 @@ public class ReplayModExtras {
|
|||||||
@Mod.EventHandler
|
@Mod.EventHandler
|
||||||
public void preInit(FMLPreInitializationEvent event) {
|
public void preInit(FMLPreInitializationEvent event) {
|
||||||
LOGGER = event.getModLog();
|
LOGGER = event.getModLog();
|
||||||
|
ReplayMod.instance.getSettingsRegistry().register(Setting.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mod.EventHandler
|
@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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ import static net.minecraft.client.Minecraft.getMinecraft;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModOnline {
|
public class ReplayModOnline {
|
||||||
public static final String MOD_ID = "replaymod-online";
|
public static final String MOD_ID = "replaymod-online";
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class GuiRegister extends AbstractGuiScreen<GuiRegister> {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String status = null;
|
String status = null;
|
||||||
if (usernameInput.getText().length() < 5) {
|
if (usernameInput.getText().length() < 1) {
|
||||||
status = "replaymod.gui.register.error.shortusername";
|
status = "replaymod.gui.register.error.shortusername";
|
||||||
} else if(!Patterns.ALPHANUMERIC_UNDERSCORE.matcher(usernameInput.getText().trim()).matches()) {
|
} else if(!Patterns.ALPHANUMERIC_UNDERSCORE.matcher(usernameInput.getText().trim()).matches()) {
|
||||||
status = "replaymod.gui.register.error.invalidname";
|
status = "replaymod.gui.register.error.invalidname";
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.replaymod.recording;
|
|||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.core.utils.Restrictions;
|
import com.replaymod.core.utils.Restrictions;
|
||||||
import com.replaymod.recording.handler.ConnectionEventHandler;
|
import com.replaymod.recording.handler.ConnectionEventHandler;
|
||||||
|
import com.replaymod.recording.handler.GuiHandler;
|
||||||
import com.replaymod.recording.packet.PacketListener;
|
import com.replaymod.recording.packet.PacketListener;
|
||||||
import io.netty.channel.ChannelDuplexHandler;
|
import io.netty.channel.ChannelDuplexHandler;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
@@ -20,6 +21,7 @@ import org.lwjgl.input.Keyboard;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModRecording {
|
public class ReplayModRecording {
|
||||||
public static final String MOD_ID = "replaymod-recording";
|
public static final String MOD_ID = "replaymod-recording";
|
||||||
@@ -57,6 +59,8 @@ public class ReplayModRecording {
|
|||||||
EventBus bus = MinecraftForge.EVENT_BUS;
|
EventBus bus = MinecraftForge.EVENT_BUS;
|
||||||
bus.register(connectionEventHandler = new ConnectionEventHandler(logger, core));
|
bus.register(connectionEventHandler = new ConnectionEventHandler(logger, core));
|
||||||
|
|
||||||
|
new GuiHandler(core).register();
|
||||||
|
|
||||||
NetworkRegistry.INSTANCE.newChannel(Restrictions.PLUGIN_CHANNEL, new RestrictionsChannelHandler());
|
NetworkRegistry.INSTANCE.newChannel(Restrictions.PLUGIN_CHANNEL, new RestrictionsChannelHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.replaymod.recording.handler;
|
||||||
|
|
||||||
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.core.SettingsRegistry;
|
||||||
|
import com.replaymod.recording.Setting;
|
||||||
|
import de.johni0702.minecraft.gui.container.GuiScreen;
|
||||||
|
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
|
||||||
|
import de.johni0702.minecraft.gui.element.GuiCheckbox;
|
||||||
|
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||||
|
import net.minecraft.client.gui.GuiMultiplayer;
|
||||||
|
import net.minecraft.client.gui.GuiWorldSelection;
|
||||||
|
import net.minecraftforge.client.event.GuiScreenEvent;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
|
||||||
|
public class GuiHandler {
|
||||||
|
|
||||||
|
private final ReplayMod mod;
|
||||||
|
|
||||||
|
public GuiHandler(ReplayMod mod) {
|
||||||
|
this.mod = mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register() {
|
||||||
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onGuiInit(GuiScreenEvent.InitGuiEvent.Post event) {
|
||||||
|
if (event.getGui() instanceof GuiWorldSelection || event.getGui() instanceof GuiMultiplayer) {
|
||||||
|
SettingsRegistry settingsRegistry = mod.getSettingsRegistry();
|
||||||
|
boolean sp = event.getGui() instanceof GuiWorldSelection;
|
||||||
|
Setting<Boolean> setting = sp ? Setting.RECORD_SINGLEPLAYER : Setting.RECORD_SERVER;
|
||||||
|
|
||||||
|
GuiCheckbox recordingCheckbox = new GuiCheckbox()
|
||||||
|
.setI18nLabel("replaymod.gui.settings.record" + (sp ? "singleplayer" : "server"))
|
||||||
|
.setChecked(settingsRegistry.get(setting));
|
||||||
|
recordingCheckbox.onClick(() -> {
|
||||||
|
settingsRegistry.set(setting, recordingCheckbox.isChecked());
|
||||||
|
settingsRegistry.save();
|
||||||
|
});
|
||||||
|
|
||||||
|
VanillaGuiScreen.setup(event.getGui()).setLayout(new CustomLayout<GuiScreen>() {
|
||||||
|
@Override
|
||||||
|
protected void layout(GuiScreen container, int width, int height) {
|
||||||
|
//size(recordingCheckbox, 200, 20);
|
||||||
|
pos(recordingCheckbox, width - width(recordingCheckbox) - 5, 5);
|
||||||
|
}
|
||||||
|
}).addElements(null, recordingCheckbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import java.util.List;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModRender {
|
public class ReplayModRender {
|
||||||
public static final String MOD_ID = "replaymod-render";
|
public static final String MOD_ID = "replaymod-render";
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File generateOutputFile(RenderSettings.EncodingPreset encodingPreset) {
|
protected File generateOutputFile(RenderSettings.EncodingPreset encodingPreset) {
|
||||||
String fileName = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(new Date());
|
String fileName = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(new Date());
|
||||||
File folder = ReplayModRender.instance.getVideoFolder();
|
File folder = ReplayModRender.instance.getVideoFolder();
|
||||||
return new File(folder, fileName + "." + encodingPreset.getFileExtension());
|
return new File(folder, fileName + "." + encodingPreset.getFileExtension());
|
||||||
@@ -447,7 +447,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
|
|||||||
config.save();
|
config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Property getConfigProperty(Configuration configuration) {
|
protected Property getConfigProperty(Configuration configuration) {
|
||||||
return configuration.get("rendersettings", "settings", "{}",
|
return configuration.get("rendersettings", "settings", "{}",
|
||||||
"Last state of the render settings GUI. Internal use only.");
|
"Last state of the render settings GUI. Internal use only.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ public abstract class MixinRenderGlobal {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
setupTerrain(viewEntity, partialTicks, camera, replayModRender_hook.nextFrameId(), playerSpectator);
|
setupTerrain(viewEntity, partialTicks, camera, replayModRender_hook.nextFrameId(), playerSpectator);
|
||||||
|
|
||||||
replayModRender_hook.updateChunks();
|
replayModRender_hook.updateChunks();
|
||||||
} while (displayListEntitiesDirty);
|
} while (displayListEntitiesDirty);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.replaymod.replay;
|
|||||||
import com.replaymod.core.utils.WrappedTimer;
|
import com.replaymod.core.utils.WrappedTimer;
|
||||||
import com.replaymod.replay.camera.CameraController;
|
import com.replaymod.replay.camera.CameraController;
|
||||||
import com.replaymod.replay.camera.CameraEntity;
|
import com.replaymod.replay.camera.CameraEntity;
|
||||||
|
import com.replaymod.replay.events.ReplayDispatchKeypressesEvent;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.settings.GameSettings;
|
import net.minecraft.client.settings.GameSettings;
|
||||||
@@ -11,6 +12,7 @@ import net.minecraft.crash.CrashReport;
|
|||||||
import net.minecraft.util.ReportedException;
|
import net.minecraft.util.ReportedException;
|
||||||
import net.minecraft.util.Timer;
|
import net.minecraft.util.Timer;
|
||||||
import net.minecraftforge.client.ForgeHooksClient;
|
import net.minecraftforge.client.ForgeHooksClient;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.input.Mouse;
|
import org.lwjgl.input.Mouse;
|
||||||
@@ -122,7 +124,9 @@ public class InputReplayTimer extends WrappedTimer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Twitch, screenshot, fullscreen, etc. (stuff that works everywhere)
|
// Twitch, screenshot, fullscreen, etc. (stuff that works everywhere)
|
||||||
mc.dispatchKeypresses();
|
if (!MinecraftForge.EVENT_BUS.post(new ReplayDispatchKeypressesEvent.Pre())) {
|
||||||
|
mc.dispatchKeypresses();
|
||||||
|
}
|
||||||
|
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
// This might be subject to change as vanilla shaders are still kinda unused in 1.8
|
// This might be subject to change as vanilla shaders are still kinda unused in 1.8
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import java.util.Optional;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModReplay {
|
public class ReplayModReplay {
|
||||||
public static final String MOD_ID = "replaymod-replay";
|
public static final String MOD_ID = "replaymod-replay";
|
||||||
@@ -194,6 +195,10 @@ public class ReplayModReplay {
|
|||||||
replayHandler = new ReplayHandler(replayFile, true);
|
replayHandler = new ReplayHandler(replayFile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void forcefullyStopReplay() {
|
||||||
|
replayHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
public ReplayMod getCore() {
|
public ReplayMod getCore() {
|
||||||
return core;
|
return core;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,12 @@ import com.google.common.io.Files;
|
|||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.core.utils.Restrictions;
|
import com.replaymod.core.utils.Restrictions;
|
||||||
import com.replaymod.replay.camera.CameraEntity;
|
import com.replaymod.replay.camera.CameraEntity;
|
||||||
|
import com.replaymod.replaystudio.io.ReplayInputStream;
|
||||||
|
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
||||||
import com.replaymod.replaystudio.replay.ReplayFile;
|
import com.replaymod.replaystudio.replay.ReplayFile;
|
||||||
|
import com.replaymod.replaystudio.studio.ReplayStudio;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufOutputStream;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.ChannelDuplexHandler;
|
import io.netty.channel.ChannelDuplexHandler;
|
||||||
import io.netty.channel.ChannelHandler.Sharable;
|
import io.netty.channel.ChannelHandler.Sharable;
|
||||||
@@ -105,10 +109,10 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
protected ChannelHandlerContext ctx;
|
protected ChannelHandlerContext ctx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data input stream from which new packets are read.
|
* The replay input stream from which new packets are read.
|
||||||
* When accessing this stream make sure to synchronize on {@code this} as it's used from multiple threads.
|
* When accessing this stream make sure to synchronize on {@code this} as it's used from multiple threads.
|
||||||
*/
|
*/
|
||||||
protected DataInputStream dis;
|
protected ReplayInputStream replayIn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The next packet that should be sent.
|
* The next packet that should be sent.
|
||||||
@@ -591,8 +595,8 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
REPLAY_LOOP:
|
REPLAY_LOOP:
|
||||||
while (!terminate) {
|
while (!terminate) {
|
||||||
synchronized (ReplaySender.this) {
|
synchronized (ReplaySender.this) {
|
||||||
if (dis == null) {
|
if (replayIn == null) {
|
||||||
dis = new DataInputStream(replayFile.getPacketData());
|
replayIn = replayFile.getPacketData();
|
||||||
}
|
}
|
||||||
// Packet loop
|
// Packet loop
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -619,7 +623,7 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
|
|
||||||
// Read the next packet if we don't already have one
|
// Read the next packet if we don't already have one
|
||||||
if (nextPacket == null) {
|
if (nextPacket == null) {
|
||||||
nextPacket = new PacketData(dis);
|
nextPacket = new PacketData(replayIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nextTimeStamp = nextPacket.timestamp;
|
int nextTimeStamp = nextPacket.timestamp;
|
||||||
@@ -676,9 +680,9 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
nextPacket = null;
|
nextPacket = null;
|
||||||
lastPacketSent = System.currentTimeMillis();
|
lastPacketSent = System.currentTimeMillis();
|
||||||
replayHandler.restartedReplay();
|
replayHandler.restartedReplay();
|
||||||
if (dis != null) {
|
if (replayIn != null) {
|
||||||
dis.close();
|
replayIn.close();
|
||||||
dis = null;
|
replayIn = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -767,17 +771,17 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
if (timestamp < lastTimeStamp) { // Restart the replay if we need to go backwards in time
|
if (timestamp < lastTimeStamp) { // Restart the replay if we need to go backwards in time
|
||||||
hasWorldLoaded = false;
|
hasWorldLoaded = false;
|
||||||
lastTimeStamp = 0;
|
lastTimeStamp = 0;
|
||||||
if (dis != null) {
|
if (replayIn != null) {
|
||||||
dis.close();
|
replayIn.close();
|
||||||
dis = null;
|
replayIn = null;
|
||||||
}
|
}
|
||||||
startFromBeginning = false;
|
startFromBeginning = false;
|
||||||
nextPacket = null;
|
nextPacket = null;
|
||||||
replayHandler.restartedReplay();
|
replayHandler.restartedReplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dis == null) {
|
if (replayIn == null) {
|
||||||
dis = new DataInputStream(replayFile.getPacketData());
|
replayIn = replayFile.getPacketData();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) { // Send packets
|
while (true) { // Send packets
|
||||||
@@ -789,7 +793,7 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
nextPacket = null;
|
nextPacket = null;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise read one from the input stream
|
// Otherwise read one from the input stream
|
||||||
pd = new PacketData(dis);
|
pd = new PacketData(replayIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nextTimeStamp = pd.timestamp;
|
int nextTimeStamp = pd.timestamp;
|
||||||
@@ -804,7 +808,7 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
} catch (EOFException eof) {
|
} catch (EOFException eof) {
|
||||||
// Shit! We hit the end before finishing our job! What shall we do now?
|
// Shit! We hit the end before finishing our job! What shall we do now?
|
||||||
// well, let's just pretend we're done...
|
// well, let's just pretend we're done...
|
||||||
dis = null;
|
replayIn = null;
|
||||||
break;
|
break;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -869,13 +873,32 @@ public class ReplaySender extends ChannelDuplexHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class PacketData {
|
private static final class PacketData {
|
||||||
|
private static final ByteBuf byteBuf = Unpooled.buffer();
|
||||||
|
private static final ByteBufOutputStream byteBufOut = new ByteBufOutputStream(byteBuf);
|
||||||
|
private static final ReplayOutputStream encoder = new ReplayOutputStream(new ReplayStudio(), byteBufOut);
|
||||||
private final int timestamp;
|
private final int timestamp;
|
||||||
private final byte[] bytes;
|
private final byte[] bytes;
|
||||||
|
|
||||||
public PacketData(DataInputStream in) throws IOException {
|
public PacketData(ReplayInputStream in) throws IOException {
|
||||||
timestamp = in.readInt();
|
com.replaymod.replaystudio.PacketData data = in.readPacket();
|
||||||
bytes = new byte[in.readInt()];
|
timestamp = (int) data.getTime();
|
||||||
in.readFully(bytes);
|
// We need to re-encode MCProtocolLib packets, so we can later decode them as NMS packets
|
||||||
|
// The main reason we aren't reading them as NMS packets is that we want ReplayStudio to be able
|
||||||
|
// to apply ViaVersion (and potentially other magic) to it.
|
||||||
|
synchronized (encoder) {
|
||||||
|
byteBuf.markReaderIndex(); // Mark the current reader and writer index (should be at start)
|
||||||
|
byteBuf.markWriterIndex();
|
||||||
|
|
||||||
|
encoder.write(data); // Re-encode packet, data will end up in byteBuf
|
||||||
|
encoder.flush();
|
||||||
|
|
||||||
|
byteBuf.skipBytes(8); // Skip packet length & timestamp
|
||||||
|
bytes = new byte[byteBuf.readableBytes()]; // Create bytes array of sufficient size
|
||||||
|
byteBuf.readBytes(bytes); // Read all data into bytes
|
||||||
|
|
||||||
|
byteBuf.resetReaderIndex(); // Reset reader & writer index for next use
|
||||||
|
byteBuf.resetWriterIndex();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.replaymod.core.SettingsRegistry;
|
|||||||
|
|
||||||
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
|
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
|
||||||
public static final Setting<Boolean> SHOW_CHAT = make("showChat", "showchat", true);
|
public static final Setting<Boolean> SHOW_CHAT = make("showChat", "showchat", true);
|
||||||
|
public static final Setting<Boolean> SHOW_SERVER_IPS = new Setting<>("showServerIPs", true);
|
||||||
public static final SettingsRegistry.MultipleChoiceSettingKeys<String> CAMERA =
|
public static final SettingsRegistry.MultipleChoiceSettingKeys<String> CAMERA =
|
||||||
new SettingsRegistry.MultipleChoiceSettingKeys<>(
|
new SettingsRegistry.MultipleChoiceSettingKeys<>(
|
||||||
"replay", "camera", "replaymod.gui.settings.camera", "replaymod.camera.classic");
|
"replay", "camera", "replaymod.gui.settings.camera", "replaymod.camera.classic");
|
||||||
@@ -15,4 +16,8 @@ public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
|
|||||||
public Setting(String key, String displayString, T defaultValue) {
|
public Setting(String key, String displayString, T defaultValue) {
|
||||||
super("replay", key, "replaymod.gui.settings." + displayString, defaultValue);
|
super("replay", key, "replaymod.gui.settings." + displayString, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Setting(String key, T defaultValue) {
|
||||||
|
super("replay", key, null, defaultValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.replaymod.replay.events;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.Cancelable;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||||
|
|
||||||
|
public abstract class ReplayDispatchKeypressesEvent extends Event {
|
||||||
|
|
||||||
|
@Cancelable
|
||||||
|
public static class Pre extends ReplayDispatchKeypressesEvent {}
|
||||||
|
}
|
||||||
@@ -5,9 +5,12 @@ import com.google.common.base.Supplier;
|
|||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.mojang.realmsclient.gui.ChatFormatting;
|
import com.mojang.realmsclient.gui.ChatFormatting;
|
||||||
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.core.SettingsRegistry;
|
||||||
import com.replaymod.core.gui.GuiReplaySettings;
|
import com.replaymod.core.gui.GuiReplaySettings;
|
||||||
import com.replaymod.core.utils.Utils;
|
import com.replaymod.core.utils.Utils;
|
||||||
import com.replaymod.replay.ReplayModReplay;
|
import com.replaymod.replay.ReplayModReplay;
|
||||||
|
import com.replaymod.replay.Setting;
|
||||||
import com.replaymod.replaystudio.replay.ReplayFile;
|
import com.replaymod.replaystudio.replay.ReplayFile;
|
||||||
import com.replaymod.replaystudio.replay.ReplayMetaData;
|
import com.replaymod.replaystudio.replay.ReplayMetaData;
|
||||||
import com.replaymod.replaystudio.replay.ZipReplayFile;
|
import com.replaymod.replaystudio.replay.ZipReplayFile;
|
||||||
@@ -18,6 +21,7 @@ import de.johni0702.minecraft.gui.container.GuiPanel;
|
|||||||
import de.johni0702.minecraft.gui.container.GuiScreen;
|
import de.johni0702.minecraft.gui.container.GuiScreen;
|
||||||
import de.johni0702.minecraft.gui.element.*;
|
import de.johni0702.minecraft.gui.element.*;
|
||||||
import de.johni0702.minecraft.gui.element.advanced.GuiResourceLoadingList;
|
import de.johni0702.minecraft.gui.element.advanced.GuiResourceLoadingList;
|
||||||
|
import de.johni0702.minecraft.gui.function.Typeable;
|
||||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||||
import de.johni0702.minecraft.gui.layout.GridLayout;
|
import de.johni0702.minecraft.gui.layout.GridLayout;
|
||||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||||
@@ -34,8 +38,10 @@ import org.apache.commons.io.filefilter.SuffixFileFilter;
|
|||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.core.helpers.Strings;
|
import org.apache.logging.log4j.core.helpers.Strings;
|
||||||
import org.lwjgl.Sys;
|
import org.lwjgl.Sys;
|
||||||
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.util.Dimension;
|
import org.lwjgl.util.Dimension;
|
||||||
import org.lwjgl.util.ReadableDimension;
|
import org.lwjgl.util.ReadableDimension;
|
||||||
|
import org.lwjgl.util.ReadablePoint;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@@ -47,7 +53,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
import static com.replaymod.replay.ReplayModReplay.LOGGER;
|
import static com.replaymod.replay.ReplayModReplay.LOGGER;
|
||||||
|
|
||||||
public class GuiReplayViewer extends GuiScreen {
|
public class GuiReplayViewer extends GuiScreen implements Typeable {
|
||||||
private final ReplayModReplay mod;
|
private final ReplayModReplay mod;
|
||||||
|
|
||||||
public final GuiResourceLoadingList<GuiReplayEntry> list = new GuiResourceLoadingList<GuiReplayEntry>(this).onSelectionChanged(new Runnable() {
|
public final GuiResourceLoadingList<GuiReplayEntry> list = new GuiResourceLoadingList<GuiReplayEntry>(this).onSelectionChanged(new Runnable() {
|
||||||
@@ -272,6 +278,18 @@ public class GuiReplayViewer extends GuiScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final GuiImage defaultThumbnail = new GuiImage().setTexture(Utils.DEFAULT_THUMBNAIL);
|
private final GuiImage defaultThumbnail = new GuiImage().setTexture(Utils.DEFAULT_THUMBNAIL);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) {
|
||||||
|
if (keyCode == Keyboard.KEY_F1) {
|
||||||
|
SettingsRegistry reg = ReplayMod.instance.getSettingsRegistry();
|
||||||
|
reg.set(Setting.SHOW_SERVER_IPS, !reg.get(Setting.SHOW_SERVER_IPS));
|
||||||
|
reg.save();
|
||||||
|
list.load();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public class GuiReplayEntry extends AbstractGuiContainer<GuiReplayEntry> implements Comparable<GuiReplayEntry> {
|
public class GuiReplayEntry extends AbstractGuiContainer<GuiReplayEntry> implements Comparable<GuiReplayEntry> {
|
||||||
public final File file;
|
public final File file;
|
||||||
public final GuiLabel name = new GuiLabel();
|
public final GuiLabel name = new GuiLabel();
|
||||||
@@ -303,7 +321,8 @@ public class GuiReplayViewer extends GuiScreen {
|
|||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
name.setText(ChatFormatting.UNDERLINE + Utils.fileNameToReplayName(file.getName()));
|
name.setText(ChatFormatting.UNDERLINE + Utils.fileNameToReplayName(file.getName()));
|
||||||
if (Strings.isEmpty(metaData.getServerName())) {
|
if (Strings.isEmpty(metaData.getServerName())
|
||||||
|
|| !ReplayMod.instance.getSettingsRegistry().get(Setting.SHOW_SERVER_IPS)) {
|
||||||
server.setI18nText("replaymod.gui.iphidden").setColor(Colors.DARK_RED);
|
server.setI18nText("replaymod.gui.iphidden").setColor(Colors.DARK_RED);
|
||||||
} else {
|
} else {
|
||||||
server.setText(metaData.getServerName());
|
server.setText(metaData.getServerName());
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.replaymod.replay.ReplayModReplay.LOGGER;
|
||||||
|
|
||||||
public class GuiHandler {
|
public class GuiHandler {
|
||||||
private static final int BUTTON_EXIT_SERVER = 1;
|
private static final int BUTTON_EXIT_SERVER = 1;
|
||||||
private static final int BUTTON_ACHIEVEMENTS = 5;
|
private static final int BUTTON_ACHIEVEMENTS = 5;
|
||||||
@@ -99,6 +101,20 @@ public class GuiHandler {
|
|||||||
return;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.getGui().width / 2 - 100,
|
GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.getGui().width / 2 - 100,
|
||||||
event.getGui().height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer"));
|
event.getGui().height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer"));
|
||||||
button.width = button.width / 2 - 2;
|
button.width = button.width / 2 - 2;
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package com.replaymod.restrictions;
|
||||||
|
|
||||||
|
import com.replaymod.core.SettingsRegistry;
|
||||||
|
import com.replaymod.core.utils.Restrictions;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.ChannelDuplexHandler;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraftforge.common.config.Configuration;
|
||||||
|
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.EventBus;
|
||||||
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||||
|
import net.minecraftforge.fml.common.network.FMLEmbeddedChannel;
|
||||||
|
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
|
||||||
|
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||||
|
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
|
||||||
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Mod(modid = ReplayModRestrictions.MOD_ID,
|
||||||
|
version = "@MOD_VERSION@",
|
||||||
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
|
acceptableRemoteVersions = "*",
|
||||||
|
serverSideOnly = true,
|
||||||
|
useMetadata = true)
|
||||||
|
public class ReplayModRestrictions {
|
||||||
|
public static final String MOD_ID = "replaymod-restrictions";
|
||||||
|
|
||||||
|
public static Logger LOGGER;
|
||||||
|
|
||||||
|
private final SettingsRegistry settingsRegistry = new SettingsRegistry();
|
||||||
|
private FMLEmbeddedChannel channel;
|
||||||
|
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void preInit(FMLPreInitializationEvent event) {
|
||||||
|
LOGGER = event.getModLog();
|
||||||
|
|
||||||
|
Configuration config = new Configuration(event.getSuggestedConfigurationFile());
|
||||||
|
config.load();
|
||||||
|
settingsRegistry.setConfiguration(config);
|
||||||
|
|
||||||
|
settingsRegistry.register(Setting.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void init(FMLInitializationEvent event) {
|
||||||
|
EventBus bus = FMLCommonHandler.instance().bus();
|
||||||
|
bus.register(this);
|
||||||
|
|
||||||
|
channel = NetworkRegistry.INSTANCE.newChannel(Restrictions.PLUGIN_CHANNEL, new RestrictionsChannelHandler()).get(Side.SERVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mod.EventHandler
|
||||||
|
public void postInit(FMLPostInitializationEvent event) throws IOException {
|
||||||
|
settingsRegistry.save(); // Save default values to disk
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChannelHandler.Sharable
|
||||||
|
private static class RestrictionsChannelHandler extends ChannelDuplexHandler {}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onUserJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||||
|
Map<String, byte[]> restrictions = new HashMap<>();
|
||||||
|
if (settingsRegistry.get(Setting.NO_XRAY)) restrictions.put("no_xray", new byte[0]);
|
||||||
|
if (settingsRegistry.get(Setting.NO_NOCLIP)) restrictions.put("no_noclip", new byte[0]);
|
||||||
|
if (settingsRegistry.get(Setting.ONLY_FIRST_PERSON)) restrictions.put("only_first_person", new byte[0]);
|
||||||
|
if (settingsRegistry.get(Setting.ONLY_RECORDING_PLAYER)) restrictions.put("only_recording_player", new byte[0]);
|
||||||
|
if (settingsRegistry.get(Setting.HIDE_COORDINATES)) restrictions.put("hide_coordinates", new byte[0]);
|
||||||
|
|
||||||
|
PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
|
||||||
|
for (Map.Entry<String, byte[]> e : restrictions.entrySet()) {
|
||||||
|
byte[] bytes = e.getKey().getBytes();
|
||||||
|
buf.writeByte(bytes.length);
|
||||||
|
buf.writeBytes(bytes);
|
||||||
|
buf.writeByte(1);
|
||||||
|
buf.writeBytes(e.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
FMLProxyPacket packet = new FMLProxyPacket(buf, Restrictions.PLUGIN_CHANNEL);
|
||||||
|
|
||||||
|
channel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
|
||||||
|
channel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(event.player);
|
||||||
|
channel.writeAndFlush(packet).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/java/com/replaymod/restrictions/Setting.java
Normal file
19
src/main/java/com/replaymod/restrictions/Setting.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.replaymod.restrictions;
|
||||||
|
|
||||||
|
import com.replaymod.core.SettingsRegistry;
|
||||||
|
|
||||||
|
public final class Setting<T> extends SettingsRegistry.SettingKeys<T> {
|
||||||
|
public static final Setting<Boolean> NO_XRAY = make("no_xray", false);
|
||||||
|
public static final Setting<Boolean> NO_NOCLIP = make("no_noclip", false);
|
||||||
|
public static final Setting<Boolean> ONLY_FIRST_PERSON = make("only_first_person", false);
|
||||||
|
public static final Setting<Boolean> ONLY_RECORDING_PLAYER = make("only_recording_player", false);
|
||||||
|
public static final Setting<Boolean> HIDE_COORDINATES = make("hide_coordinates", false);
|
||||||
|
|
||||||
|
private static <T> Setting<T> make(String key, T defaultValue) {
|
||||||
|
return new Setting<>("restrictions", key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Setting(String category, String key, T defaultValue) {
|
||||||
|
super(category, key, null, defaultValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,10 @@ package com.replaymod.simplepathing;
|
|||||||
|
|
||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.core.events.SettingsChangedEvent;
|
import com.replaymod.core.events.SettingsChangedEvent;
|
||||||
|
import com.replaymod.replay.ReplayModReplay;
|
||||||
import com.replaymod.replay.events.ReplayCloseEvent;
|
import com.replaymod.replay.events.ReplayCloseEvent;
|
||||||
import com.replaymod.replay.events.ReplayOpenEvent;
|
import com.replaymod.replay.events.ReplayOpenEvent;
|
||||||
|
import com.replaymod.replay.gui.overlay.GuiReplayOverlay;
|
||||||
import com.replaymod.replaystudio.pathing.path.Keyframe;
|
import com.replaymod.replaystudio.pathing.path.Keyframe;
|
||||||
import com.replaymod.simplepathing.SPTimeline.SPPath;
|
import com.replaymod.simplepathing.SPTimeline.SPPath;
|
||||||
import com.replaymod.simplepathing.gui.GuiPathing;
|
import com.replaymod.simplepathing.gui.GuiPathing;
|
||||||
@@ -20,6 +22,7 @@ import org.lwjgl.input.Keyboard;
|
|||||||
version = "@MOD_VERSION@",
|
version = "@MOD_VERSION@",
|
||||||
acceptedMinecraftVersions = "@MC_VERSION@",
|
acceptedMinecraftVersions = "@MC_VERSION@",
|
||||||
acceptableRemoteVersions = "*",
|
acceptableRemoteVersions = "*",
|
||||||
|
clientSideOnly = true,
|
||||||
useMetadata = true)
|
useMetadata = true)
|
||||||
public class ReplayModSimplePathing {
|
public class ReplayModSimplePathing {
|
||||||
public static final String MOD_ID = "replaymod-simplepathing";
|
public static final String MOD_ID = "replaymod-simplepathing";
|
||||||
@@ -81,20 +84,34 @@ public class ReplayModSimplePathing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GuiReplayOverlay getReplayOverlay() {
|
||||||
|
return ReplayModReplay.instance.getReplayHandler().getOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
private SPTimeline currentTimeline;
|
private SPTimeline currentTimeline;
|
||||||
|
|
||||||
@Getter
|
|
||||||
private SPPath selectedPath;
|
private SPPath selectedPath;
|
||||||
@Getter
|
@Getter
|
||||||
private long selectedTime;
|
private long selectedTime;
|
||||||
|
|
||||||
|
public SPPath getSelectedPath() {
|
||||||
|
if (getReplayOverlay().timeline.getSelectedMarker() != null) {
|
||||||
|
selectedPath = null;
|
||||||
|
selectedTime = 0;
|
||||||
|
}
|
||||||
|
return selectedPath;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSelected(Keyframe keyframe) {
|
public boolean isSelected(Keyframe keyframe) {
|
||||||
return selectedPath != null && currentTimeline.getKeyframe(selectedPath, selectedTime) == keyframe;
|
return getSelectedPath() != null && currentTimeline.getKeyframe(selectedPath, selectedTime) == keyframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelected(SPPath path, long time) {
|
public void setSelected(SPPath path, long time) {
|
||||||
selectedPath = path;
|
selectedPath = path;
|
||||||
selectedTime = time;
|
selectedTime = time;
|
||||||
|
if (selectedPath != null) {
|
||||||
|
getReplayOverlay().timeline.setSelectedMarker(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentTimeline(SPTimeline newTimeline) {
|
public void setCurrentTimeline(SPTimeline newTimeline) {
|
||||||
|
|||||||
@@ -124,5 +124,8 @@ public net.minecraft.entity.EntityLivingBase field_184628_bn # activeItemStackUs
|
|||||||
# EntityLivingBase
|
# EntityLivingBase
|
||||||
public net.minecraft.client.particle.Particle *
|
public net.minecraft.client.particle.Particle *
|
||||||
|
|
||||||
|
# ScreenShotHelper
|
||||||
|
public net.minecraft.util.ScreenShotHelper func_74290_a(Ljava/io/File;)Ljava/io/File; # getTimestampedPNGFileForDirectory
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
# public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName
|
# public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName
|
||||||
|
|||||||
Submodule src/main/resources/assets/replaymod/lang updated: 8d77fe0697...692a676556
@@ -134,6 +134,22 @@
|
|||||||
"screenshots": [],
|
"screenshots": [],
|
||||||
"dependencies": []
|
"dependencies": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"modid": "replaymod-restrictions",
|
||||||
|
"name": "Replay Mod - Restrictions",
|
||||||
|
"description": "Server-side Restrictions Module of the ReplayMod - Restrict what clients can do in replays",
|
||||||
|
"version": "${version}",
|
||||||
|
"mcversion": "${mcversion}",
|
||||||
|
"url": "https://replaymod.com",
|
||||||
|
"updateUrl": "https://replaymod.com/download",
|
||||||
|
"authorList": [
|
||||||
|
"CrushedPixel",
|
||||||
|
"johni0702"
|
||||||
|
],
|
||||||
|
"logoFile": "replaymod_logo.png",
|
||||||
|
"screenshots": [],
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"modid": "replaymod-compat",
|
"modid": "replaymod-compat",
|
||||||
"name": "Replay Mod - Compatibility",
|
"name": "Replay Mod - Compatibility",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"package": "com.replaymod.render.mixin",
|
"package": "com.replaymod.render.mixin",
|
||||||
"mixins": [
|
"mixins": [],
|
||||||
|
"server": [],
|
||||||
|
"client": [
|
||||||
"MixinEntityRenderer",
|
"MixinEntityRenderer",
|
||||||
"MixinFrustum",
|
"MixinFrustum",
|
||||||
"MixinParticleManager",
|
"MixinParticleManager",
|
||||||
@@ -9,8 +11,6 @@
|
|||||||
"MixinRenderGlobal",
|
"MixinRenderGlobal",
|
||||||
"MixinRenderManager"
|
"MixinRenderManager"
|
||||||
],
|
],
|
||||||
"server": [],
|
|
||||||
"client": [],
|
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"minVersion": "0.6.11",
|
"minVersion": "0.6.11",
|
||||||
"refmap": "mixins.replaymod.refmap.json"
|
"refmap": "mixins.replaymod.refmap.json"
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"package": "com.replaymod.replay.mixin",
|
"package": "com.replaymod.replay.mixin",
|
||||||
"mixins": [
|
"mixins": [],
|
||||||
|
"server": [],
|
||||||
|
"client": [
|
||||||
"MixinGuiSpectator",
|
"MixinGuiSpectator",
|
||||||
"MixinParticleManager",
|
"MixinParticleManager",
|
||||||
"MixinPlayerControllerMP",
|
"MixinPlayerControllerMP",
|
||||||
@@ -13,8 +15,6 @@
|
|||||||
"MixinViewFrustum",
|
"MixinViewFrustum",
|
||||||
"MixinWorldClient"
|
"MixinWorldClient"
|
||||||
],
|
],
|
||||||
"server": [],
|
|
||||||
"client": [],
|
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"minVersion": "0.6.11",
|
"minVersion": "0.6.11",
|
||||||
"refmap": "mixins.replaymod.refmap.json"
|
"refmap": "mixins.replaymod.refmap.json"
|
||||||
|
|||||||
Reference in New Issue
Block a user