Release 2.5.2
This commit is contained in:
@@ -16,8 +16,6 @@ Build the mod via Gradle as explained above at least once (`./gradlew compileJav
|
|||||||
Then import the Gradle project from within IDEA: File -> Open -> build.gradle -> Open as Project
|
Then import the Gradle project from within IDEA: File -> Open -> build.gradle -> Open as Project
|
||||||
Finally configure IDEA to build everything by itself instead of delegating it to Gradle (cause that is slow): File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle -> Build and run using: IntelliJ IDEA
|
Finally configure IDEA to build everything by itself instead of delegating it to Gradle (cause that is slow): File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle -> Build and run using: IntelliJ IDEA
|
||||||
|
|
||||||
The generation of run configurations for 1.14+ currently depends on https://github.com/FabricMC/fabric-loom/pull/236
|
|
||||||
|
|
||||||
### Eclipse
|
### Eclipse
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ buildscript {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven {
|
maven {
|
||||||
name = "fabric"
|
name = "fabric"
|
||||||
@@ -32,7 +34,7 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.2'
|
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.2'
|
||||||
if (fabric) {
|
if (fabric) {
|
||||||
classpath 'fabric-loom:fabric-loom.gradle.plugin:0.4-SNAPSHOT'
|
classpath 'fabric-loom:fabric-loom.gradle.plugin:0.5-SNAPSHOT'
|
||||||
} else if (mcVersion >= 11400) {
|
} else if (mcVersion >= 11400) {
|
||||||
classpath('net.minecraftforge.gradle:ForgeGradle:3.+'){
|
classpath('net.minecraftforge.gradle:ForgeGradle:3.+'){
|
||||||
exclude group: 'trove', module: 'trove' // preprocessor/idea requires more recent one
|
exclude group: 'trove', module: 'trove' // preprocessor/idea requires more recent one
|
||||||
@@ -189,7 +191,7 @@ repositories {
|
|||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven {
|
maven {
|
||||||
name = "SpongePowered Repo"
|
name = "SpongePowered Repo"
|
||||||
url = "http://repo.spongepowered.org/maven/"
|
url = "https://repo.spongepowered.org/maven/"
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
name = "fabric"
|
name = "fabric"
|
||||||
@@ -272,7 +274,7 @@ dependencies {
|
|||||||
|
|
||||||
if (!FABRIC) {
|
if (!FABRIC) {
|
||||||
// Mixin 0.8 is no longer compatible with MC 1.11.2 or older
|
// Mixin 0.8 is no longer compatible with MC 1.11.2 or older
|
||||||
def mixinVersion = mcVersion >= 11200 ? '0.8' : '0.7.10-SNAPSHOT'
|
def mixinVersion = mcVersion >= 11200 ? '0.8.2' : '0.7.11-SNAPSHOT'
|
||||||
annotationProcessor "org.spongepowered:mixin:$mixinVersion"
|
annotationProcessor "org.spongepowered:mixin:$mixinVersion"
|
||||||
compileOnly "org.spongepowered:mixin:$mixinVersion"
|
compileOnly "org.spongepowered:mixin:$mixinVersion"
|
||||||
shade("org.spongepowered:mixin:$mixinVersion") {
|
shade("org.spongepowered:mixin:$mixinVersion") {
|
||||||
@@ -283,6 +285,7 @@ dependencies {
|
|||||||
annotationProcessor 'com.google.code.gson:gson:2.2.4'
|
annotationProcessor 'com.google.code.gson:gson:2.2.4'
|
||||||
annotationProcessor 'com.google.guava:guava:21.0'
|
annotationProcessor 'com.google.guava:guava:21.0'
|
||||||
annotationProcessor 'org.ow2.asm:asm-tree:6.2'
|
annotationProcessor 'org.ow2.asm:asm-tree:6.2'
|
||||||
|
annotationProcessor 'org.apache.logging.log4j:log4j-core:2.0-beta9'
|
||||||
}
|
}
|
||||||
shadow 'com.googlecode.mp4parser:isoparser:1.1.7'
|
shadow 'com.googlecode.mp4parser:isoparser:1.1.7'
|
||||||
shadow 'org.apache.commons:commons-exec:1.3'
|
shadow 'org.apache.commons:commons-exec:1.3'
|
||||||
@@ -309,7 +312,7 @@ dependencies {
|
|||||||
|
|
||||||
shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8'
|
shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8'
|
||||||
|
|
||||||
shadow "com.github.ReplayMod:ReplayStudio:dac74cc", shadeExclusions
|
shadow "com.github.ReplayMod:ReplayStudio:a1f82a7", shadeExclusions
|
||||||
|
|
||||||
implementation(jGui){
|
implementation(jGui){
|
||||||
transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those
|
transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those
|
||||||
2
jGui
2
jGui
Submodule jGui updated: 6b16892d64...6641836321
@@ -2,7 +2,7 @@ import groovy.json.JsonOutput
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("fabric-loom") version "0.4-SNAPSHOT" apply false
|
id("fabric-loom") version "0.5-SNAPSHOT" apply false
|
||||||
id("com.replaymod.preprocess") version "24ac087"
|
id("com.replaymod.preprocess") version "24ac087"
|
||||||
id("com.github.hierynomus.license") version "0.15.0"
|
id("com.github.hierynomus.license") version "0.15.0"
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
jcenter()
|
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
@@ -49,6 +48,8 @@ val replayModVersions = listOf(
|
|||||||
"1.16.4"
|
"1.16.4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rootProject.buildFileName = "root.gradle.kts"
|
||||||
|
|
||||||
include(":jGui")
|
include(":jGui")
|
||||||
project(":jGui").apply {
|
project(":jGui").apply {
|
||||||
projectDir = file("jGui")
|
projectDir = file("jGui")
|
||||||
@@ -58,7 +59,7 @@ jGuiVersions.forEach { version ->
|
|||||||
include(":jGui:$version")
|
include(":jGui:$version")
|
||||||
project(":jGui:$version").apply {
|
project(":jGui:$version").apply {
|
||||||
projectDir = file("jGui/versions/$version")
|
projectDir = file("jGui/versions/$version")
|
||||||
buildFileName = "../common.gradle"
|
buildFileName = "../../build.gradle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +67,6 @@ replayModVersions.forEach { version ->
|
|||||||
include(":$version")
|
include(":$version")
|
||||||
project(":$version").apply {
|
project(":$version").apply {
|
||||||
projectDir = file("versions/$version")
|
projectDir = file("versions/$version")
|
||||||
buildFileName = "../common.gradle"
|
buildFileName = "../../build.gradle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -476,6 +476,14 @@ public class ReplayMod implements
|
|||||||
String name = path.getFileName().toString();
|
String name = path.getFileName().toString();
|
||||||
if (name.endsWith(".mcpr.tmp") && Files.isDirectory(path)) {
|
if (name.endsWith(".mcpr.tmp") && Files.isDirectory(path)) {
|
||||||
Path original = path.resolveSibling(FilenameUtils.getBaseName(name));
|
Path original = path.resolveSibling(FilenameUtils.getBaseName(name));
|
||||||
|
Path noRecoverMarker = original.resolveSibling(original.getFileName() + ".no_recover");
|
||||||
|
if (Files.exists(noRecoverMarker)) {
|
||||||
|
// This file, when its markers are processed, doesn't actually result in any replays.
|
||||||
|
// So we don't really need to recover it either, let's just get rid of it.
|
||||||
|
FileUtils.deleteDirectory(path.toFile());
|
||||||
|
Files.delete(noRecoverMarker);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
new RestoreReplayGui(this, GuiScreen.wrap(mc.currentScreen), original.toFile()).display();
|
new RestoreReplayGui(this, GuiScreen.wrap(mc.currentScreen), original.toFile()).display();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,9 +80,16 @@ import org.lwjgl.glfw.GLFW;
|
|||||||
//$$ import java.io.IOException;
|
//$$ import java.io.IOException;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
//#if MC>=11400
|
||||||
|
import net.minecraft.client.sound.PositionedSoundInstance;
|
||||||
|
//#else
|
||||||
|
//$$ import net.minecraft.client.audio.PositionedSoundRecord;
|
||||||
|
//#endif
|
||||||
|
|
||||||
//#if MC>=10904
|
//#if MC>=10904
|
||||||
import com.replaymod.render.blend.mixin.ParticleAccessor;
|
import com.replaymod.render.blend.mixin.ParticleAccessor;
|
||||||
import net.minecraft.client.particle.Particle;
|
import net.minecraft.client.particle.Particle;
|
||||||
|
import net.minecraft.sound.SoundEvent;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
@@ -758,6 +765,20 @@ public class MCVer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void playSound(Identifier sound) {
|
||||||
|
getMinecraft().getSoundManager().play(
|
||||||
|
//#if MC>=11400
|
||||||
|
PositionedSoundInstance.master(new SoundEvent(sound), 1.0F)
|
||||||
|
//#elseif MC>=10904
|
||||||
|
//$$ PositionedSoundRecord.getMasterRecord(new SoundEvent(sound), 1.0F)
|
||||||
|
//#elseif MC>=10800
|
||||||
|
//$$ PositionedSoundRecord.create(sound, 1.0F)
|
||||||
|
//#else
|
||||||
|
//$$ PositionedSoundRecord.createPositionedSoundRecord(sound, 1.0F)
|
||||||
|
//#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
private static Boolean hasOptifine;
|
private static Boolean hasOptifine;
|
||||||
public static boolean hasOptifine() {
|
public static boolean hasOptifine() {
|
||||||
|
|||||||
@@ -272,6 +272,10 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
// Immediately close the saving popup, the user doesn't care about it
|
// Immediately close the saving popup, the user doesn't care about it
|
||||||
core.runLater(guiSavingReplay::close);
|
core.runLater(guiSavingReplay::close);
|
||||||
|
|
||||||
|
// If we crash right here, on the next start we'll prompt the user for recovery
|
||||||
|
// but we don't really want that, so drop a marker file to skip recovery for this replay.
|
||||||
|
Files.createFile(outputPath.resolveSibling(outputPath.getFileName() + ".no_recover"));
|
||||||
|
|
||||||
// We still have the replay, so we just save it (at least for a few weeks) in case they change their mind
|
// We still have the replay, so we just save it (at least for a few weeks) in case they change their mind
|
||||||
String replayName = FilenameUtils.getBaseName(outputPath.getFileName().toString());
|
String replayName = FilenameUtils.getBaseName(outputPath.getFileName().toString());
|
||||||
Path rawFolder = ReplayMod.instance.getRawReplayFolder();
|
Path rawFolder = ReplayMod.instance.getRawReplayFolder();
|
||||||
|
|||||||
@@ -443,4 +443,32 @@ public class RenderSettings {
|
|||||||
public boolean isHighPerformance() {
|
public boolean isHighPerformance() {
|
||||||
return highPerformance;
|
return highPerformance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RenderSettings{" +
|
||||||
|
"renderMethod=" + renderMethod +
|
||||||
|
", encodingPreset=" + encodingPreset +
|
||||||
|
", videoWidth=" + videoWidth +
|
||||||
|
", videoHeight=" + videoHeight +
|
||||||
|
", framesPerSecond=" + framesPerSecond +
|
||||||
|
", bitRate=" + bitRate +
|
||||||
|
", outputFile=" + outputFile +
|
||||||
|
", renderNameTags=" + renderNameTags +
|
||||||
|
", stabilizeYaw=" + stabilizeYaw +
|
||||||
|
", stabilizePitch=" + stabilizePitch +
|
||||||
|
", stabilizeRoll=" + stabilizeRoll +
|
||||||
|
", chromaKeyingColor=" + chromaKeyingColor +
|
||||||
|
", sphericalFovX=" + sphericalFovX +
|
||||||
|
", sphericalFovY=" + sphericalFovY +
|
||||||
|
", injectSphericalMetadata=" + injectSphericalMetadata +
|
||||||
|
", depthMap=" + depthMap +
|
||||||
|
", cameraPathExport=" + cameraPathExport +
|
||||||
|
", antiAliasing=" + antiAliasing +
|
||||||
|
", exportCommand='" + exportCommand + '\'' +
|
||||||
|
", exportArgumentsPreBgra='" + exportArgumentsPreBgra + '\'' +
|
||||||
|
", exportArguments='" + exportArguments + '\'' +
|
||||||
|
", highPerformance=" + highPerformance +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.replaymod.render.ReplayModRender.LOGGER;
|
import static com.replaymod.render.ReplayModRender.LOGGER;
|
||||||
|
|
||||||
@@ -148,8 +149,15 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements
|
|||||||
renderButton.onClick(() -> {
|
renderButton.onClick(() -> {
|
||||||
LOGGER.trace("Render button clicked");
|
LOGGER.trace("Render button clicked");
|
||||||
List<RenderJob> renderQueue = new ArrayList<>();
|
List<RenderJob> renderQueue = new ArrayList<>();
|
||||||
for (Entry entry : selectedEntries) {
|
if (selectedEntries.isEmpty()) {
|
||||||
renderQueue.add(entry.job);
|
renderQueue.addAll(jobs);
|
||||||
|
} else {
|
||||||
|
Set<RenderJob> selectedJobs = selectedEntries.stream().map(it -> it.job).collect(Collectors.toSet());
|
||||||
|
for (RenderJob job : jobs) {
|
||||||
|
if (selectedJobs.contains(job)) {
|
||||||
|
renderQueue.add(job);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ReplayMod.instance.runLaterWithoutLock(() -> processQueue(container, replayHandler, renderQueue, () -> {}));
|
ReplayMod.instance.runLaterWithoutLock(() -> processQueue(container, replayHandler, renderQueue, () -> {}));
|
||||||
});
|
});
|
||||||
@@ -337,7 +345,7 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements
|
|||||||
addButton.setEnabled(timelineSupplier != null);
|
addButton.setEnabled(timelineSupplier != null);
|
||||||
editButton.setEnabled(selected == 1);
|
editButton.setEnabled(selected == 1);
|
||||||
removeButton.setEnabled(selected >= 1);
|
removeButton.setEnabled(selected >= 1);
|
||||||
renderButton.setEnabled(selected > 0);
|
renderButton.setEnabled(jobs.size() > 0);
|
||||||
renderButton.setI18nLabel("replaymod.gui.renderqueue.render" + (selected > 0 ? "selected" : "all"));
|
renderButton.setI18nLabel("replaymod.gui.renderqueue.render" + (selected > 0 ? "selected" : "all"));
|
||||||
|
|
||||||
String[] compatError = VideoRenderer.checkCompat();
|
String[] compatError = VideoRenderer.checkCompat();
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
public void run() {
|
public void run() {
|
||||||
GuiFileChooserPopup popup = GuiFileChooserPopup.openSaveGui(GuiRenderSettings.this, "replaymod.gui.save",
|
GuiFileChooserPopup popup = GuiFileChooserPopup.openSaveGui(GuiRenderSettings.this, "replaymod.gui.save",
|
||||||
encodingPresetDropdown.getSelectedValue().getFileExtension());
|
encodingPresetDropdown.getSelectedValue().getFileExtension());
|
||||||
popup.setFolder(outputFile.getParentFile());
|
popup.setFolder(getParentFile(outputFile));
|
||||||
popup.setFileName(outputFile.getName());
|
popup.setFileName(outputFile.getName());
|
||||||
Futures.addCallback(
|
Futures.addCallback(
|
||||||
popup.getFuture(),
|
popup.getFuture(),
|
||||||
@@ -538,13 +538,13 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
bitRateUnit.setSelected(0);
|
bitRateUnit.setSelected(0);
|
||||||
}
|
}
|
||||||
File savedOutputFile = settings.getOutputFile();
|
File savedOutputFile = settings.getOutputFile();
|
||||||
if (savedOutputFile == null || !savedOutputFile.getParentFile().exists()) {
|
if (savedOutputFile == null || !getParentFile(savedOutputFile).exists()) {
|
||||||
this.outputFile = generateOutputFile(encodingPreset);
|
this.outputFile = generateOutputFile(encodingPreset);
|
||||||
userDefinedOutputFileName = false;
|
userDefinedOutputFileName = false;
|
||||||
} else if (savedOutputFile.exists()) {
|
} else if (savedOutputFile.exists()) {
|
||||||
String name = generateOutputFile(encodingPreset).getName();
|
String name = generateOutputFile(encodingPreset).getName();
|
||||||
boolean isFolder = savedOutputFile.isDirectory() && !savedOutputFile.getName().endsWith(".exr");
|
boolean isFolder = savedOutputFile.isDirectory() && !savedOutputFile.getName().endsWith(".exr");
|
||||||
this.outputFile = new File(isFolder ? savedOutputFile : savedOutputFile.getParentFile(), name);
|
this.outputFile = new File(isFolder ? savedOutputFile : getParentFile(savedOutputFile), name);
|
||||||
userDefinedOutputFileName = false;
|
userDefinedOutputFileName = false;
|
||||||
} else {
|
} else {
|
||||||
this.outputFile = conformExtension(savedOutputFile, encodingPreset);
|
this.outputFile = conformExtension(savedOutputFile, encodingPreset);
|
||||||
@@ -588,7 +588,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
videoHeight.getInteger(),
|
videoHeight.getInteger(),
|
||||||
frameRateSlider.getValue() + 10,
|
frameRateSlider.getValue() + 10,
|
||||||
bitRateField.getInteger() << (10 * bitRateUnit.getSelected()),
|
bitRateField.getInteger() << (10 * bitRateUnit.getSelected()),
|
||||||
serialize && !userDefinedOutputFileName ? outputFile.getParentFile() : outputFile,
|
serialize && !userDefinedOutputFileName ? getParentFile(outputFile) : outputFile,
|
||||||
nametagCheckbox.isChecked(),
|
nametagCheckbox.isChecked(),
|
||||||
stabilizeYaw.isChecked() && (serialize || stabilizeYaw.isEnabled()),
|
stabilizeYaw.isChecked() && (serialize || stabilizeYaw.isEnabled()),
|
||||||
stabilizePitch.isChecked() && (serialize || stabilizePitch.isEnabled()),
|
stabilizePitch.isChecked() && (serialize || stabilizePitch.isEnabled()),
|
||||||
@@ -617,7 +617,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
|
|
||||||
public void setOutputFileBaseName(String base) {
|
public void setOutputFileBaseName(String base) {
|
||||||
RenderSettings.EncodingPreset preset = encodingPresetDropdown.getSelectedValue();
|
RenderSettings.EncodingPreset preset = encodingPresetDropdown.getSelectedValue();
|
||||||
File file = new File(outputFile.getParentFile(), base + "." + preset.getFileExtension());
|
File file = new File(getParentFile(outputFile), base + "." + preset.getFileExtension());
|
||||||
// Ensure the file name is valid
|
// Ensure the file name is valid
|
||||||
try {
|
try {
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
@@ -634,7 +634,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
if (name.contains(".")) {
|
if (name.contains(".")) {
|
||||||
name = name.substring(0, name.lastIndexOf('.'));
|
name = name.substring(0, name.lastIndexOf('.'));
|
||||||
}
|
}
|
||||||
return new File(file.getParentFile(), name + "." + preset.getFileExtension());
|
return new File(getParentFile(file), name + "." + preset.getFileExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Path getSettingsPath() {
|
protected Path getSettingsPath() {
|
||||||
@@ -677,4 +677,10 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
screen.setBackground(AbstractGuiScreen.Background.NONE);
|
screen.setBackground(AbstractGuiScreen.Background.NONE);
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static File getParentFile(File file) {
|
||||||
|
File parent = file.getParentFile();
|
||||||
|
// parent this can be null if file is just a name (i.e. in CWD)
|
||||||
|
return parent == null ? new File(".") : parent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import com.replaymod.render.gui.GuiRenderingDone;
|
|||||||
import com.replaymod.render.gui.GuiVideoRenderer;
|
import com.replaymod.render.gui.GuiVideoRenderer;
|
||||||
import com.replaymod.render.metadata.MetadataInjector;
|
import com.replaymod.render.metadata.MetadataInjector;
|
||||||
import com.replaymod.render.mixin.WorldRendererAccessor;
|
import com.replaymod.render.mixin.WorldRendererAccessor;
|
||||||
import com.replaymod.render.utils.SoundHandler;
|
|
||||||
import com.replaymod.replay.ReplayHandler;
|
import com.replaymod.replay.ReplayHandler;
|
||||||
import com.replaymod.replaystudio.pathing.path.Keyframe;
|
import com.replaymod.replaystudio.pathing.path.Keyframe;
|
||||||
import com.replaymod.replaystudio.pathing.path.Path;
|
import com.replaymod.replaystudio.pathing.path.Path;
|
||||||
@@ -29,6 +28,7 @@ import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
|||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import com.mojang.blaze3d.platform.GLX;
|
import com.mojang.blaze3d.platform.GLX;
|
||||||
import net.minecraft.client.gl.Framebuffer;
|
import net.minecraft.client.gl.Framebuffer;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.crash.CrashException;
|
import net.minecraft.util.crash.CrashException;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.client.render.RenderTickCounter;
|
import net.minecraft.client.render.RenderTickCounter;
|
||||||
@@ -422,7 +422,7 @@ public class VideoRenderer implements RenderInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new SoundHandler().playRenderSuccessSound();
|
MCVer.playSound(new Identifier("replaymod", "render_success"));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!hasFailed() && ffmpegWriter != null) {
|
if (!hasFailed() && ffmpegWriter != null) {
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.replaymod.render.utils;
|
|
||||||
|
|
||||||
import com.replaymod.core.versions.MCVer;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
|
|
||||||
import javax.sound.sampled.AudioInputStream;
|
|
||||||
import javax.sound.sampled.AudioSystem;
|
|
||||||
import javax.sound.sampled.Clip;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class SoundHandler {
|
|
||||||
|
|
||||||
private final Identifier successSoundLocation = new Identifier("replaymod", "render_success.wav");
|
|
||||||
|
|
||||||
public void playRenderSuccessSound() {
|
|
||||||
playSound(successSoundLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plays a <b>.wav</b> Sound from a ResourceLocation. This method does <b>not</b> respect Game Settings like Audio Volume.
|
|
||||||
* @param loc The Sound File's ResourceLocation
|
|
||||||
*/
|
|
||||||
public void playSound(Identifier loc) {
|
|
||||||
try {
|
|
||||||
InputStream is = MCVer.getMinecraft().getResourceManager().getResource(loc).getInputStream();
|
|
||||||
byte[] bytes = IOUtils.toByteArray(is);
|
|
||||||
is.close();
|
|
||||||
AudioInputStream ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes));
|
|
||||||
|
|
||||||
Clip clip = AudioSystem.getClip();
|
|
||||||
clip.open(ais);
|
|
||||||
clip.start();
|
|
||||||
} catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -339,9 +339,8 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int currentTimeStamp() {
|
public int currentTimeStamp() {
|
||||||
if (asyncMode) {
|
if (asyncMode && !paused()) {
|
||||||
int timePassed = (int) (System.currentTimeMillis() - lastPacketSent);
|
return (int) ((System.currentTimeMillis() - realTimeStart) * realTimeStartSpeed);
|
||||||
return lastTimeStamp + (int) (timePassed * getReplaySpeed());
|
|
||||||
} else {
|
} else {
|
||||||
return lastTimeStamp;
|
return lastTimeStamp;
|
||||||
}
|
}
|
||||||
@@ -864,7 +863,11 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setReplaySpeed(final double d) {
|
public void setReplaySpeed(final double d) {
|
||||||
if(d != 0) this.replaySpeed = d;
|
if (d != 0) {
|
||||||
|
this.replaySpeed = d;
|
||||||
|
this.realTimeStartSpeed = d;
|
||||||
|
this.realTimeStart = System.currentTimeMillis() - (long) (lastTimeStamp / d);
|
||||||
|
}
|
||||||
TimerAccessor timer = (TimerAccessor) ((MinecraftAccessor) mc).getTimer();
|
TimerAccessor timer = (TimerAccessor) ((MinecraftAccessor) mc).getTimer();
|
||||||
//#if MC>=11200
|
//#if MC>=11200
|
||||||
timer.setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK / (float) d);
|
timer.setTickLength(WrappedTimer.DEFAULT_MS_PER_TICK / (float) d);
|
||||||
@@ -878,9 +881,18 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The real time at which the last packet was sent in milliseconds.
|
* Timestamp in milliseconds of when we started (or would have started when taking pauses and speed into account)
|
||||||
|
* the playback of the replay.
|
||||||
|
* Updated only when replay speed changes or on pause/unpause but definitely not on every packet to prevent gradual
|
||||||
|
* drifting.
|
||||||
*/
|
*/
|
||||||
private long lastPacketSent;
|
private long realTimeStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The replay speed used for {@link #realTimeStart}.
|
||||||
|
* If the target speed differs from this one, the timestamp is recalculated.
|
||||||
|
*/
|
||||||
|
private double realTimeStartSpeed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There is no waiting performed until a packet with at least this timestamp is reached (but not yet sent).
|
* There is no waiting performed until a packet with at least this timestamp is reached (but not yet sent).
|
||||||
@@ -936,15 +948,13 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
// If we aren't jumping and the world has already been loaded (no dirt-screens) then wait
|
// If we aren't jumping and the world has already been loaded (no dirt-screens) then wait
|
||||||
// the required amount to get proper packet timing
|
// the required amount to get proper packet timing
|
||||||
if (!isHurrying() && hasWorldLoaded) {
|
if (!isHurrying() && hasWorldLoaded) {
|
||||||
// How much time should have passed
|
// Timestamp of when the next packet should be sent
|
||||||
int timeWait = (int) Math.round((nextTimeStamp - lastTimeStamp) / replaySpeed);
|
long expectedTime = realTimeStart + (long) (nextTimeStamp / replaySpeed);
|
||||||
// How much time did pass
|
long now = System.currentTimeMillis();
|
||||||
long timeDiff = System.currentTimeMillis() - lastPacketSent;
|
// If the packet should not yet be sent, wait a bit
|
||||||
// How much time we need to wait to make up for the difference
|
if (expectedTime > now) {
|
||||||
long timeToSleep = Math.max(0, timeWait - timeDiff);
|
Thread.sleep(expectedTime - now);
|
||||||
|
}
|
||||||
Thread.sleep(timeToSleep);
|
|
||||||
lastPacketSent = System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process packet
|
// Process packet
|
||||||
@@ -961,7 +971,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
|
|
||||||
replayHandler.moveCameraToTargetPosition();
|
replayHandler.moveCameraToTargetPosition();
|
||||||
|
|
||||||
// Pause after jumping
|
// Pause after jumping (this will also reset realTimeStart accordingly)
|
||||||
setReplaySpeed(0);
|
setReplaySpeed(0);
|
||||||
}
|
}
|
||||||
} catch (EOFException eof) {
|
} catch (EOFException eof) {
|
||||||
@@ -988,7 +998,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
loginPhase = true;
|
loginPhase = true;
|
||||||
startFromBeginning = false;
|
startFromBeginning = false;
|
||||||
nextPacket = null;
|
nextPacket = null;
|
||||||
lastPacketSent = System.currentTimeMillis();
|
realTimeStart = System.currentTimeMillis();
|
||||||
if (replayIn != null) {
|
if (replayIn != null) {
|
||||||
replayIn.close();
|
replayIn.close();
|
||||||
replayIn = null;
|
replayIn = null;
|
||||||
@@ -1133,7 +1143,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This might be required if we change to async mode anytime soon
|
// This might be required if we change to async mode anytime soon
|
||||||
lastPacketSent = System.currentTimeMillis();
|
realTimeStart = System.currentTimeMillis() - (long) (timestamp / replaySpeed);
|
||||||
lastTimeStamp = timestamp;
|
lastTimeStamp = timestamp;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import net.minecraft.util.hit.HitResult;
|
|||||||
//$$ import net.minecraft.util.math.RayTraceResult;
|
//$$ import net.minecraft.util.math.RayTraceResult;
|
||||||
//$$ import net.minecraft.util.text.ITextComponent;
|
//$$ import net.minecraft.util.text.ITextComponent;
|
||||||
//$$ import net.minecraft.world.World;
|
//$$ import net.minecraft.world.World;
|
||||||
|
//$$ import net.minecraftforge.fml.common.gameevent.InputEvent;
|
||||||
//$$
|
//$$
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
//$$ import net.minecraft.util.math.RayTraceFluidMode;
|
//$$ import net.minecraft.util.math.RayTraceFluidMode;
|
||||||
@@ -637,12 +638,11 @@ public class CameraEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canSpectate(Entity e) {
|
public boolean canSpectate(Entity e) {
|
||||||
return e != null && !e.isInvisible()
|
return e != null
|
||||||
//#if MC>=10800
|
//#if MC<10800
|
||||||
&& (e instanceof PlayerEntity || e instanceof MobEntity || e instanceof ItemFrameEntity);
|
//$$ && e instanceof EntityPlayer // cannot be more generic since 1.7.10 has no concept of eye height
|
||||||
//#else
|
|
||||||
//$$ && e instanceof EntityPlayer; // cannot be more generic since 1.7.10 has no concept of eye height
|
|
||||||
//#endif
|
//#endif
|
||||||
|
&& !e.isInvisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if MC<11400
|
//#if MC<11400
|
||||||
@@ -695,6 +695,16 @@ public class CameraEntity
|
|||||||
|
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
{ on(KeyBindingEventCallback.EVENT, CameraEntity.this::handleInputEvents); }
|
{ on(KeyBindingEventCallback.EVENT, CameraEntity.this::handleInputEvents); }
|
||||||
|
//#elseif MC<11400
|
||||||
|
//$$ @SubscribeEvent
|
||||||
|
//$$ public void onKeyEvent(InputEvent.KeyInputEvent event) {
|
||||||
|
//$$ handleInputEvents();
|
||||||
|
//$$ }
|
||||||
|
//$$
|
||||||
|
//$$ @SubscribeEvent
|
||||||
|
//$$ public void onMouseInput(InputEvent.MouseInputEvent event) {
|
||||||
|
//$$ handleInputEvents();
|
||||||
|
//$$ }
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
//#if FABRIC>=1
|
//#if FABRIC>=1
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static com.replaymod.core.utils.Utils.error;
|
import static com.replaymod.core.utils.Utils.error;
|
||||||
@@ -287,7 +288,9 @@ public class GuiPathing {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void onFailure(Throwable t) {
|
||||||
t.printStackTrace();
|
if (!(t instanceof CancellationException)) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
overlay.setCloseable(true);
|
overlay.setCloseable(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Binary file not shown.
5
src/main/resources/assets/replaymod/sounds.json
Normal file
5
src/main/resources/assets/replaymod/sounds.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"render_success": {
|
||||||
|
"sounds": [{ "name": "replaymod:render_success" }]
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/main/resources/assets/replaymod/sounds/render_success.ogg
Normal file
BIN
src/main/resources/assets/replaymod/sounds/render_success.ogg
Normal file
Binary file not shown.
@@ -1 +1 @@
|
|||||||
2.5.1
|
2.5.2
|
||||||
|
|||||||
Reference in New Issue
Block a user