Release 2.6.1
This commit is contained in:
@@ -332,7 +332,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:a67fb11", shadeExclusions
|
shadow "com.github.ReplayMod:ReplayStudio:c9de2f5", 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: 71d361746e...31bcfabe67
@@ -68,6 +68,12 @@ fun command(vararg cmd: Any): List<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun generateVersionsJson(): Map<String, Any> {
|
fun generateVersionsJson(): Map<String, Any> {
|
||||||
|
val versionComparator = compareBy<String>(
|
||||||
|
{ (it.split(".").getOrNull(0) ?: "0").toInt() },
|
||||||
|
{ (it.split(".").getOrNull(1) ?: "0").toInt() },
|
||||||
|
{ (it.split(".").getOrNull(2) ?: "0").toInt() }
|
||||||
|
)
|
||||||
|
|
||||||
// Find all tag-style releases by listing all tags
|
// Find all tag-style releases by listing all tags
|
||||||
val tagVersions = command("git", "for-each-ref", "--sort=taggerdate", "--format=%(refname:short)", "refs/tags")
|
val tagVersions = command("git", "for-each-ref", "--sort=taggerdate", "--format=%(refname:short)", "refs/tags")
|
||||||
|
|
||||||
@@ -85,6 +91,9 @@ fun generateVersionsJson(): Map<String, Any> {
|
|||||||
.filter { it != "core" }
|
.filter { it != "core" }
|
||||||
// Internal project used to automatically remap from Forge 1.12.2 to Fabric 1.14.4
|
// Internal project used to automatically remap from Forge 1.12.2 to Fabric 1.14.4
|
||||||
.filter { it != "1.14.4-forge" }
|
.filter { it != "1.14.4-forge" }
|
||||||
|
// We dropped 1.7.10 with the Gradle 7 update but still kept its source in case someone
|
||||||
|
// volunteers to update FG 1.2 to Gradle 7.
|
||||||
|
.filterNot { it == "1.7.10" && versionComparator.compare(version, "2.6.0") >= 0 }
|
||||||
mcVersions.map { "$it-$version" }
|
mcVersions.map { "$it-$version" }
|
||||||
}.flatten()
|
}.flatten()
|
||||||
|
|
||||||
@@ -92,11 +101,7 @@ fun generateVersionsJson(): Map<String, Any> {
|
|||||||
val mcVersions = versions
|
val mcVersions = versions
|
||||||
.map {it.substring(0, it.indexOf("-"))}
|
.map {it.substring(0, it.indexOf("-"))}
|
||||||
.distinct()
|
.distinct()
|
||||||
.sortedWith(compareBy(
|
.sortedWith(versionComparator)
|
||||||
{ (it.split(".").getOrNull(0) ?: "0").toInt() },
|
|
||||||
{ (it.split(".").getOrNull(1) ?: "0").toInt() },
|
|
||||||
{ (it.split(".").getOrNull(2) ?: "0").toInt() }
|
|
||||||
))
|
|
||||||
|
|
||||||
val promos = mutableMapOf<String, String>()
|
val promos = mutableMapOf<String, String>()
|
||||||
val root = mutableMapOf<String, Any>(
|
val root = mutableMapOf<String, Any>(
|
||||||
@@ -126,6 +131,14 @@ fun generateVersionsJson(): Map<String, Any> {
|
|||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val writeVersionsJson by tasks.registering {
|
||||||
|
doLast {
|
||||||
|
val versionsRoot = generateVersionsJson()
|
||||||
|
val versionsJson = JsonOutput.prettyPrint(JsonOutput.toJson(versionsRoot))
|
||||||
|
File("versions.json").writeText(versionsJson)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val doRelease by tasks.registering {
|
val doRelease by tasks.registering {
|
||||||
doLast {
|
doLast {
|
||||||
// Parse version
|
// Parse version
|
||||||
|
|||||||
@@ -325,6 +325,18 @@ public class ReplayMod implements Module, Scheduler {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cleanup leftover no_recover files
|
||||||
|
try (DirectoryStream<Path> paths = Files.newDirectoryStream(getReplayFolder())) {
|
||||||
|
for (Path path : paths) {
|
||||||
|
String name = path.getFileName().toString();
|
||||||
|
if (name.endsWith(".no_recover")) {
|
||||||
|
Files.delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,25 @@ import static com.replaymod.core.versions.MCVer.getMinecraft;
|
|||||||
|
|
||||||
public class GuiBackgroundProcesses extends EventRegistrations {
|
public class GuiBackgroundProcesses extends EventRegistrations {
|
||||||
private GuiPanel panel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(10));
|
private GuiPanel panel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(10));
|
||||||
|
private boolean reentrant;
|
||||||
|
|
||||||
{ on(InitScreenCallback.EVENT, (screen, buttons) -> onGuiInit(screen)); }
|
{ on(InitScreenCallback.EVENT, (screen, buttons) -> onGuiInit(screen)); }
|
||||||
private void onGuiInit(net.minecraft.client.gui.screen.Screen guiScreen) {
|
private void onGuiInit(net.minecraft.client.gui.screen.Screen guiScreen) {
|
||||||
if (guiScreen != getMinecraft().currentScreen) return; // people tend to construct GuiScreens without opening them
|
if (guiScreen != getMinecraft().currentScreen) return; // people tend to construct GuiScreens without opening them
|
||||||
|
|
||||||
VanillaGuiScreen vanillaGui = VanillaGuiScreen.wrap(guiScreen);
|
VanillaGuiScreen vanillaGui;
|
||||||
|
// TODO Workaround for #473 and #501 where another mod opens a new gui in response to the MCGuiScreen.init we
|
||||||
|
// call from VanillaGuiScreen.register.
|
||||||
|
// Ideally, we don't have an hidden inner MCGuiScreen and instead have a common parent class for
|
||||||
|
// AbstractGuiScreen, AbstractGuiOverlay and VanillaGuiScreen which deals with the common things. That's
|
||||||
|
// quite a bit of changes though, so I'll keep that for 2.7 and have this workaround until then.
|
||||||
|
if (reentrant) return;
|
||||||
|
try {
|
||||||
|
reentrant = true;
|
||||||
|
vanillaGui = VanillaGuiScreen.wrap(guiScreen);
|
||||||
|
} finally {
|
||||||
|
reentrant = false;
|
||||||
|
}
|
||||||
vanillaGui.setLayout(new CustomLayout<GuiScreen>(vanillaGui.getLayout()) {
|
vanillaGui.setLayout(new CustomLayout<GuiScreen>(vanillaGui.getLayout()) {
|
||||||
@Override
|
@Override
|
||||||
protected void layout(GuiScreen container, int width, int height) {
|
protected void layout(GuiScreen container, int width, int height) {
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
//#if FABRIC>=1
|
|
||||||
package com.replaymod.core.mixin;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.pack.PackListWidget;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
//#if MC>=11600
|
|
||||||
import net.minecraft.client.gui.screen.pack.PackScreen;
|
|
||||||
import net.minecraft.client.gui.screen.pack.ResourcePackOrganizer;
|
|
||||||
//#else
|
|
||||||
//$$ import net.minecraft.client.resource.ClientResourcePackProfile;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC>=11600
|
|
||||||
@Mixin(PackScreen.class)
|
|
||||||
//#else
|
|
||||||
//$$ @Mixin(ResourcePackListWidget.class)
|
|
||||||
//#endif
|
|
||||||
public abstract class Mixin_HideDynamicResourcePacks {
|
|
||||||
//#if MC>=11600
|
|
||||||
@Inject(method = "method_29672", at = @At("HEAD"), cancellable = true)
|
|
||||||
private void hideInternalPacks(PackListWidget packListWidget, ResourcePackOrganizer.Pack pack, CallbackInfo info) {
|
|
||||||
//#else
|
|
||||||
//$$ @Inject(method = "add", at = @At("HEAD"), cancellable = true)
|
|
||||||
//$$ private void hideInternalPacks(ResourcePackListWidget.ResourcePackEntry entry, CallbackInfo info) {
|
|
||||||
//$$ ClientResourcePackProfile pack = entry.getPack();
|
|
||||||
//#endif
|
|
||||||
String name = pack.getDisplayName().asString();
|
|
||||||
if (name.equals("replaymod_lang") || name.equals("replaymod_jgui")) {
|
|
||||||
info.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//#endif
|
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
//#if FABRIC>=1
|
||||||
|
package com.replaymod.core.mixin;
|
||||||
|
|
||||||
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.core.versions.LangResourcePack;
|
||||||
|
import net.minecraft.resource.ResourcePack;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.stream.Collector;
|
||||||
|
|
||||||
|
|
||||||
|
//#if MC>=11600
|
||||||
|
@Mixin(net.minecraft.resource.ResourcePackManager.class)
|
||||||
|
//#else
|
||||||
|
//$$ @Mixin(net.minecraft.client.MinecraftClient.class)
|
||||||
|
//#endif
|
||||||
|
public class Mixin_InjectDynamicResourcePacks {
|
||||||
|
@ModifyArg(
|
||||||
|
//#if MC>=11600
|
||||||
|
method = "createResourcePacks",
|
||||||
|
//#elseif MC>=11500
|
||||||
|
//$$ method = { "<init>", "reloadResources" },
|
||||||
|
//#else
|
||||||
|
//$$ method = { "init", "reloadResources" },
|
||||||
|
//#endif
|
||||||
|
at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;collect(Ljava/util/stream/Collector;)Ljava/lang/Object;")
|
||||||
|
)
|
||||||
|
private Collector<ResourcePack, ?, ?> injectReplayModPacks(Collector<ResourcePack, ?, ?> collector) {
|
||||||
|
collector = append(collector, new LangResourcePack());
|
||||||
|
if (ReplayMod.jGuiResourcePack != null) {
|
||||||
|
collector = append(collector, ReplayMod.jGuiResourcePack);
|
||||||
|
}
|
||||||
|
return collector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T, A, R> Collector<T, A, R> append(Collector<T, A, R> collector, T value) {
|
||||||
|
BiConsumer<A, T> accumulator = collector.accumulator();
|
||||||
|
return Collector.of(
|
||||||
|
collector.supplier(),
|
||||||
|
accumulator,
|
||||||
|
collector.combiner(),
|
||||||
|
result -> {
|
||||||
|
accumulator.accept(result, value);
|
||||||
|
return collector.finisher().apply(result);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//#if FABRIC>=1
|
|
||||||
package com.replaymod.core.mixin;
|
|
||||||
|
|
||||||
import com.replaymod.core.ReplayMod;
|
|
||||||
import com.replaymod.core.versions.LangResourcePack;
|
|
||||||
import net.minecraft.client.resource.ClientBuiltinResourcePackProvider;
|
|
||||||
import net.minecraft.resource.ResourcePackProfile;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
//#if MC>=11600
|
|
||||||
import net.minecraft.resource.ResourcePackSource;
|
|
||||||
//#else
|
|
||||||
//$$ import java.util.Map;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
@Mixin(ClientBuiltinResourcePackProvider.class)
|
|
||||||
public class Mixin_RegisterDynamicResourcePacks {
|
|
||||||
@Inject(method = "register", at = @At("RETURN"))
|
|
||||||
//#if MC>=11600
|
|
||||||
private void registerReplayMod(Consumer<ResourcePackProfile> consumer, ResourcePackProfile.Factory factory, CallbackInfo ci) {
|
|
||||||
//#else
|
|
||||||
//$$ private <T extends ResourcePackProfile> void registerReplayMod(Map<String, T> map, ResourcePackProfile.Factory<T> factory, CallbackInfo ci) {
|
|
||||||
//$$ Consumer<T> consumer = (pack) -> map.put(pack.getName(), pack);
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
consumer.accept(ResourcePackProfile.of(
|
|
||||||
LangResourcePack.NAME,
|
|
||||||
true,
|
|
||||||
LangResourcePack::new,
|
|
||||||
factory,
|
|
||||||
ResourcePackProfile.InsertionPosition.BOTTOM
|
|
||||||
//#if MC>=11600
|
|
||||||
, ResourcePackSource.PACK_SOURCE_BUILTIN
|
|
||||||
//#endif
|
|
||||||
));
|
|
||||||
|
|
||||||
if (ReplayMod.jGuiResourcePack != null) {
|
|
||||||
consumer.accept(ResourcePackProfile.of(
|
|
||||||
ReplayMod.JGUI_RESOURCE_PACK_NAME,
|
|
||||||
true,
|
|
||||||
() -> ReplayMod.jGuiResourcePack,
|
|
||||||
factory,
|
|
||||||
ResourcePackProfile.InsertionPosition.BOTTOM
|
|
||||||
//#if MC>=11600
|
|
||||||
, ResourcePackSource.PACK_SOURCE_BUILTIN
|
|
||||||
//#endif
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//#endif
|
|
||||||
@@ -9,6 +9,7 @@ import net.minecraft.client.world.ClientWorld;
|
|||||||
import net.minecraft.client.render.Tessellator;
|
import net.minecraft.client.render.Tessellator;
|
||||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||||
import net.minecraft.client.sound.PositionedSoundInstance;
|
import net.minecraft.client.sound.PositionedSoundInstance;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.util.crash.CrashReportSection;
|
import net.minecraft.util.crash.CrashReportSection;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
@@ -215,6 +216,15 @@ class Patterns {
|
|||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Pattern
|
||||||
|
private static PlayerInventory getInventory(PlayerEntity entity) {
|
||||||
|
//#if MC>=11700
|
||||||
|
//$$ return entity.getInventory();
|
||||||
|
//#else
|
||||||
|
return entity.inventory;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
@Pattern
|
@Pattern
|
||||||
private static Iterable<Entity> loadedEntityList(ClientWorld world) {
|
private static Iterable<Entity> loadedEntityList(ClientWorld world) {
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ public class ScreenshotRenderer implements RenderInfo {
|
|||||||
Window window = mc.getWindow();
|
Window window = mc.getWindow();
|
||||||
int widthBefore = window.getFramebufferWidth();
|
int widthBefore = window.getFramebufferWidth();
|
||||||
int heightBefore = window.getFramebufferHeight();
|
int heightBefore = window.getFramebufferHeight();
|
||||||
boolean hideGUIBefore = mc.options.hudHidden;
|
|
||||||
mc.options.hudHidden = true;
|
|
||||||
|
|
||||||
ForceChunkLoadingHook clrg = new ForceChunkLoadingHook(mc.worldRenderer);
|
ForceChunkLoadingHook clrg = new ForceChunkLoadingHook(mc.worldRenderer);
|
||||||
|
|
||||||
@@ -46,7 +44,6 @@ public class ScreenshotRenderer implements RenderInfo {
|
|||||||
|
|
||||||
clrg.uninstall();
|
clrg.uninstall();
|
||||||
|
|
||||||
mc.options.hudHidden = hideGUIBefore;
|
|
||||||
resizeMainWindow(mc, widthBefore, heightBefore);
|
resizeMainWindow(mc, widthBefore, heightBefore);
|
||||||
return true;
|
return true;
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.replaymod.pathing.player;
|
|||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.replaymod.replay.ReplayHandler;
|
import com.replaymod.replay.ReplayHandler;
|
||||||
import com.replaymod.replaystudio.pathing.path.Timeline;
|
import com.replaymod.replaystudio.pathing.path.Timeline;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeline player using the system time.
|
* Timeline player using the system time.
|
||||||
@@ -21,6 +22,9 @@ public class RealtimeTimelinePlayer extends AbstractTimelinePlayer {
|
|||||||
*/
|
*/
|
||||||
private long startTime;
|
private long startTime;
|
||||||
|
|
||||||
|
private boolean loadingResources;
|
||||||
|
private long timeBeforeResourceLoading;
|
||||||
|
|
||||||
public RealtimeTimelinePlayer(ReplayHandler replayHandler) {
|
public RealtimeTimelinePlayer(ReplayHandler replayHandler) {
|
||||||
super(replayHandler);
|
super(replayHandler);
|
||||||
}
|
}
|
||||||
@@ -28,6 +32,7 @@ public class RealtimeTimelinePlayer extends AbstractTimelinePlayer {
|
|||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> start(Timeline timeline) {
|
public ListenableFuture<Void> start(Timeline timeline) {
|
||||||
firstFrame = true;
|
firstFrame = true;
|
||||||
|
loadingResources = false;
|
||||||
return super.start(timeline);
|
return super.start(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,9 +40,25 @@ public class RealtimeTimelinePlayer extends AbstractTimelinePlayer {
|
|||||||
public void onTick() {
|
public void onTick() {
|
||||||
if (secondFrame) {
|
if (secondFrame) {
|
||||||
secondFrame = false;
|
secondFrame = false;
|
||||||
startTime = System.currentTimeMillis();
|
startTime = System.currentTimeMillis() - startOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#if MC>=11400
|
||||||
|
if (MinecraftClient.getInstance().getOverlay() != null) {
|
||||||
|
if (!loadingResources) {
|
||||||
|
timeBeforeResourceLoading = getTimePassed();
|
||||||
|
loadingResources = true;
|
||||||
|
}
|
||||||
|
super.onTick();
|
||||||
|
return;
|
||||||
|
} else if (loadingResources && !firstFrame) {
|
||||||
|
startTime = System.currentTimeMillis() - timeBeforeResourceLoading;
|
||||||
|
loadingResources = false;
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
|
||||||
super.onTick();
|
super.onTick();
|
||||||
|
|
||||||
if (firstFrame) {
|
if (firstFrame) {
|
||||||
firstFrame = false;
|
firstFrame = false;
|
||||||
secondFrame = true;
|
secondFrame = true;
|
||||||
@@ -46,6 +67,8 @@ public class RealtimeTimelinePlayer extends AbstractTimelinePlayer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimePassed() {
|
public long getTimePassed() {
|
||||||
return startOffset + (firstFrame ? 0 : System.currentTimeMillis() - startTime);
|
if (firstFrame) return 0;
|
||||||
|
if (loadingResources) return timeBeforeResourceLoading;
|
||||||
|
return System.currentTimeMillis() - startTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,8 +166,14 @@ public class RecordingEventHandler extends EventRegistrations {
|
|||||||
lastY = player.getY();
|
lastY = player.getY();
|
||||||
lastZ = player.getZ();
|
lastZ = player.getZ();
|
||||||
|
|
||||||
|
//#if MC>=10904
|
||||||
|
final double maxRelDist = 8.0;
|
||||||
|
//#else
|
||||||
|
//$$ final double maxRelDist = 4.0;
|
||||||
|
//#endif
|
||||||
|
|
||||||
Packet packet;
|
Packet packet;
|
||||||
if (force || Math.abs(dx) > 8.0 || Math.abs(dy) > 8.0 || Math.abs(dz) > 8.0) {
|
if (force || Math.abs(dx) > maxRelDist || Math.abs(dy) > maxRelDist || Math.abs(dz) > maxRelDist) {
|
||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
packet = new EntityPositionS2CPacket(player);
|
packet = new EntityPositionS2CPacket(player);
|
||||||
//#else
|
//#else
|
||||||
|
|||||||
@@ -275,7 +275,8 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
// If we crash right here, on the next start we'll prompt the user for recovery
|
// 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.
|
// 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"));
|
Path noRecoverMarker = outputPath.resolveSibling(outputPath.getFileName() + ".no_recover");
|
||||||
|
Files.createFile(noRecoverMarker);
|
||||||
|
|
||||||
// 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());
|
||||||
@@ -287,6 +288,9 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
|
|||||||
Files.createDirectories(rawPath.getParent());
|
Files.createDirectories(rawPath.getParent());
|
||||||
replayFile.saveTo(rawPath.toFile());
|
replayFile.saveTo(rawPath.toFile());
|
||||||
replayFile.close();
|
replayFile.close();
|
||||||
|
|
||||||
|
// Done, clean up the marker
|
||||||
|
Files.delete(noRecoverMarker);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.google.gson.annotations.JsonAdapter;
|
|||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.replaymod.core.utils.FileTypeAdapter;
|
import com.replaymod.core.utils.FileTypeAdapter;
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
|
import de.johni0702.minecraft.gui.utils.lwjgl.Color;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor;
|
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
@@ -153,7 +154,7 @@ public class RenderSettings {
|
|||||||
private final boolean stabilizeYaw;
|
private final boolean stabilizeYaw;
|
||||||
private final boolean stabilizePitch;
|
private final boolean stabilizePitch;
|
||||||
private final boolean stabilizeRoll;
|
private final boolean stabilizeRoll;
|
||||||
private final ReadableColor chromaKeyingColor;
|
private final Color chromaKeyingColor;
|
||||||
private final int sphericalFovX;
|
private final int sphericalFovX;
|
||||||
private final int sphericalFovY;
|
private final int sphericalFovY;
|
||||||
private final boolean injectSphericalMetadata;
|
private final boolean injectSphericalMetadata;
|
||||||
@@ -173,6 +174,32 @@ public class RenderSettings {
|
|||||||
|
|
||||||
private final boolean highPerformance;
|
private final boolean highPerformance;
|
||||||
|
|
||||||
|
public RenderSettings() {
|
||||||
|
this(
|
||||||
|
RenderSettings.RenderMethod.DEFAULT,
|
||||||
|
RenderSettings.EncodingPreset.MP4_CUSTOM,
|
||||||
|
1920,
|
||||||
|
1080,
|
||||||
|
60,
|
||||||
|
20 << 20,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
360,
|
||||||
|
180,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
RenderSettings.AntiAliasing.NONE,
|
||||||
|
"",
|
||||||
|
RenderSettings.EncodingPreset.MP4_CUSTOM.getValue(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public RenderSettings(
|
public RenderSettings(
|
||||||
RenderMethod renderMethod,
|
RenderMethod renderMethod,
|
||||||
EncodingPreset encodingPreset,
|
EncodingPreset encodingPreset,
|
||||||
@@ -207,7 +234,7 @@ public class RenderSettings {
|
|||||||
this.stabilizeYaw = stabilizeYaw;
|
this.stabilizeYaw = stabilizeYaw;
|
||||||
this.stabilizePitch = stabilizePitch;
|
this.stabilizePitch = stabilizePitch;
|
||||||
this.stabilizeRoll = stabilizeRoll;
|
this.stabilizeRoll = stabilizeRoll;
|
||||||
this.chromaKeyingColor = chromaKeyingColor;
|
this.chromaKeyingColor = chromaKeyingColor == null ? null : new Color(chromaKeyingColor);
|
||||||
this.sphericalFovX = sphericalFovX;
|
this.sphericalFovX = sphericalFovX;
|
||||||
this.sphericalFovY = sphericalFovY;
|
this.sphericalFovY = sphericalFovY;
|
||||||
this.injectSphericalMetadata = injectSphericalMetadata;
|
this.injectSphericalMetadata = injectSphericalMetadata;
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package com.replaymod.render.gui;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.InstanceCreator;
|
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
import com.replaymod.render.RenderSettings;
|
import com.replaymod.render.RenderSettings;
|
||||||
@@ -31,7 +29,6 @@ import de.johni0702.minecraft.gui.utils.Consumer;
|
|||||||
import de.johni0702.minecraft.gui.utils.Utils;
|
import de.johni0702.minecraft.gui.utils.Utils;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.Color;
|
import de.johni0702.minecraft.gui.utils.lwjgl.Color;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor;
|
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
|
||||||
import net.minecraft.client.gui.screen.NoticeScreen;
|
import net.minecraft.client.gui.screen.NoticeScreen;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
@@ -331,16 +328,13 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
}
|
}
|
||||||
RenderSettings settings = null;
|
RenderSettings settings = null;
|
||||||
try {
|
try {
|
||||||
settings = new GsonBuilder()
|
settings = new Gson().fromJson(json, RenderSettings.class);
|
||||||
.registerTypeAdapter(RenderSettings.class, (InstanceCreator<RenderSettings>) type -> getDefaultRenderSettings())
|
|
||||||
.registerTypeAdapter(ReadableColor.class, new Gson().getAdapter(Color.class))
|
|
||||||
.create().fromJson(json, RenderSettings.class);
|
|
||||||
} catch (JsonSyntaxException e) {
|
} catch (JsonSyntaxException e) {
|
||||||
LOGGER.error("Parsing render settings:", e);
|
LOGGER.error("Parsing render settings:", e);
|
||||||
LOGGER.error("Raw JSON: {}", json);
|
LOGGER.error("Raw JSON: {}", json);
|
||||||
}
|
}
|
||||||
if (settings == null) {
|
if (settings == null) {
|
||||||
settings = getDefaultRenderSettings();
|
settings = new RenderSettings();
|
||||||
}
|
}
|
||||||
load(settings);
|
load(settings);
|
||||||
}
|
}
|
||||||
@@ -508,7 +502,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
/* encodingPreset can be null from a previously supported and later removed preset */
|
/* encodingPreset can be null from a previously supported and later removed preset */
|
||||||
boolean invalidEncodingPreset = encodingPreset == null || !encodingPreset.isSupported();
|
boolean invalidEncodingPreset = encodingPreset == null || !encodingPreset.isSupported();
|
||||||
if (invalidEncodingPreset) {
|
if (invalidEncodingPreset) {
|
||||||
encodingPreset = getDefaultRenderSettings().getEncodingPreset();
|
encodingPreset = new RenderSettings().getEncodingPreset();
|
||||||
}
|
}
|
||||||
encodingPresetDropdown.setSelected(encodingPreset);
|
encodingPresetDropdown.setSelected(encodingPreset);
|
||||||
videoWidth.setValue(settings.getTargetVideoWidth());
|
videoWidth.setValue(settings.getTargetVideoWidth());
|
||||||
@@ -628,11 +622,6 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
|
|||||||
return ReplayModRender.instance.getRenderSettingsPath();
|
return ReplayModRender.instance.getRenderSettingsPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RenderSettings getDefaultRenderSettings() {
|
|
||||||
return new RenderSettings(RenderSettings.RenderMethod.DEFAULT, RenderSettings.EncodingPreset.MP4_CUSTOM, 1920, 1080, 60, 20 << 20, null,
|
|
||||||
true, false, false, false, null, 360, 180, false, false, false, RenderSettings.AntiAliasing.NONE, "", RenderSettings.EncodingPreset.MP4_CUSTOM.getValue(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void open() {
|
public void open() {
|
||||||
super.open();
|
super.open();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.replaymod.core.events.SettingsChangedCallback;
|
|||||||
import com.replaymod.replay.ReplayHandler;
|
import com.replaymod.replay.ReplayHandler;
|
||||||
import com.replaymod.replay.events.RenderHotbarCallback;
|
import com.replaymod.replay.events.RenderHotbarCallback;
|
||||||
import com.replaymod.replay.events.RenderSpectatorCrosshairCallback;
|
import com.replaymod.replay.events.RenderSpectatorCrosshairCallback;
|
||||||
|
import com.replaymod.replay.mixin.EntityPlayerAccessor;
|
||||||
import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
||||||
import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback;
|
import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback;
|
||||||
import com.replaymod.core.utils.Utils;
|
import com.replaymod.core.utils.Utils;
|
||||||
@@ -21,9 +22,11 @@ import net.minecraft.client.MinecraftClient;
|
|||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.mob.MobEntity;
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
import net.minecraft.entity.decoration.ItemFrameEntity;
|
import net.minecraft.entity.decoration.ItemFrameEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.stat.StatHandler;
|
import net.minecraft.stat.StatHandler;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
@@ -246,9 +249,37 @@ public class CameraEntity
|
|||||||
this.lastRenderX = to.lastRenderX;
|
this.lastRenderX = to.lastRenderX;
|
||||||
this.lastRenderY = to.lastRenderY + yOffset;
|
this.lastRenderY = to.lastRenderY + yOffset;
|
||||||
this.lastRenderZ = to.lastRenderZ;
|
this.lastRenderZ = to.lastRenderZ;
|
||||||
|
if (to instanceof LivingEntity) {
|
||||||
|
LivingEntity toLiving = (LivingEntity) to;
|
||||||
|
this.headYaw = toLiving.headYaw;
|
||||||
|
this.prevHeadYaw = toLiving.prevHeadYaw;
|
||||||
|
} else {
|
||||||
|
this.headYaw = to.yaw;
|
||||||
|
this.prevHeadYaw = to.prevYaw;
|
||||||
|
}
|
||||||
updateBoundingBox();
|
updateBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#if MC>=11400
|
||||||
|
@Override
|
||||||
|
public float getYaw(float tickDelta) {
|
||||||
|
Entity view = this.client.getCameraEntity();
|
||||||
|
if (view != null && view != this) {
|
||||||
|
return this.prevHeadYaw + (this.headYaw - this.prevHeadYaw) * tickDelta;
|
||||||
|
}
|
||||||
|
return super.getYaw(tickDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getPitch(float tickDelta) {
|
||||||
|
Entity view = this.client.getCameraEntity();
|
||||||
|
if (view != null && view != this) {
|
||||||
|
return this.prevPitch + (this.pitch - this.prevPitch) * tickDelta;
|
||||||
|
}
|
||||||
|
return super.getPitch(tickDelta);
|
||||||
|
}
|
||||||
|
//#endif
|
||||||
|
|
||||||
private void updateBoundingBox() {
|
private void updateBoundingBox() {
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
float width = getWidth();
|
float width = getWidth();
|
||||||
@@ -618,6 +649,43 @@ public class CameraEntity
|
|||||||
//#if MC>=10800
|
//#if MC>=10800
|
||||||
this.noClip = this.isSpectator();
|
this.noClip = this.isSpectator();
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
syncInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PlayerInventory originalInventory = this.inventory;
|
||||||
|
|
||||||
|
// If we are spectating a player, "steal" its inventory so the rendering code knows what item(s) to render
|
||||||
|
// and if we aren't, then reset ours.
|
||||||
|
private void syncInventory() {
|
||||||
|
Entity view = this.client.getCameraEntity();
|
||||||
|
PlayerEntity viewPlayer = view != this && view instanceof PlayerEntity ? (PlayerEntity) view : null;
|
||||||
|
EntityPlayerAccessor cameraA = (EntityPlayerAccessor) this;
|
||||||
|
EntityPlayerAccessor viewPlayerA = (EntityPlayerAccessor) viewPlayer;
|
||||||
|
|
||||||
|
//#if MC>=11100
|
||||||
|
ItemStack empty = ItemStack.EMPTY;
|
||||||
|
//#else
|
||||||
|
//$$ ItemStack empty = null;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// TODO switch to replacing the entire inventory for 1.14+ as well, should be easier and faster
|
||||||
|
//#if MC>=11400
|
||||||
|
this.equipStack(EquipmentSlot.HEAD, viewPlayer != null ? viewPlayer.getEquippedStack(EquipmentSlot.HEAD) : empty);
|
||||||
|
this.equipStack(EquipmentSlot.MAINHAND, viewPlayer != null ? viewPlayer.getEquippedStack(EquipmentSlot.MAINHAND) : empty);
|
||||||
|
this.equipStack(EquipmentSlot.OFFHAND, viewPlayer != null ? viewPlayer.getEquippedStack(EquipmentSlot.OFFHAND) : empty);
|
||||||
|
//#else
|
||||||
|
//$$ this.inventory = viewPlayer != null ? viewPlayer.inventory : originalInventory;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
//#if MC>=10904
|
||||||
|
cameraA.setItemStackMainHand(viewPlayerA != null ? viewPlayerA.getItemStackMainHand() : empty);
|
||||||
|
this.preferredHand = viewPlayer != null ? viewPlayer.preferredHand : Hand.MAIN_HAND;
|
||||||
|
cameraA.setActiveItemStackUseCount(viewPlayerA != null ? viewPlayerA.getActiveItemStackUseCount() : 0);
|
||||||
|
//#else
|
||||||
|
//$$ cameraA.setItemInUse(viewPlayerA != null ? viewPlayerA.getItemInUse() : empty);
|
||||||
|
//$$ cameraA.setItemInUseCount(viewPlayerA != null ? viewPlayerA.getItemInUseCount() : 0);
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleInputEvents() {
|
private void handleInputEvents() {
|
||||||
@@ -639,7 +707,7 @@ public class CameraEntity
|
|||||||
this.lastRenderYaw = this.renderYaw;
|
this.lastRenderYaw = this.renderYaw;
|
||||||
this.lastRenderPitch = this.renderPitch;
|
this.lastRenderPitch = this.renderPitch;
|
||||||
this.renderPitch = this.renderPitch + (this.pitch - this.renderPitch) * 0.5f;
|
this.renderPitch = this.renderPitch + (this.pitch - this.renderPitch) * 0.5f;
|
||||||
this.renderYaw = this.renderYaw + (this.yaw - this.renderYaw) * 0.5f;
|
this.renderYaw = this.renderYaw + (this.headYaw - this.renderYaw) * 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canSpectate(Entity e) {
|
public boolean canSpectate(Entity e) {
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
package com.replaymod.replay.camera;
|
package com.replaymod.replay.camera;
|
||||||
|
|
||||||
import com.replaymod.replay.ReplayModReplay;
|
import com.replaymod.replay.ReplayModReplay;
|
||||||
import com.replaymod.replay.mixin.EntityPlayerAccessor;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.options.KeyBinding;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
|
|
||||||
//#if MC>=11400
|
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
//#else
|
//#else
|
||||||
@@ -55,27 +49,6 @@ public class SpectatorCameraController implements CameraController {
|
|||||||
Entity view = mc.getCameraEntity();
|
Entity view = mc.getCameraEntity();
|
||||||
if (view != null && view != camera) {
|
if (view != null && view != camera) {
|
||||||
camera.setCameraPosRot(mc.getCameraEntity());
|
camera.setCameraPosRot(mc.getCameraEntity());
|
||||||
// If it's a player, also 'steal' its inventory so the rendering code knows what item to render
|
|
||||||
if (view instanceof PlayerEntity) {
|
|
||||||
PlayerEntity viewPlayer = (PlayerEntity) view;
|
|
||||||
//#if MC>=11400
|
|
||||||
camera.equipStack(EquipmentSlot.HEAD, viewPlayer.getEquippedStack(EquipmentSlot.HEAD));
|
|
||||||
camera.equipStack(EquipmentSlot.MAINHAND, viewPlayer.getEquippedStack(EquipmentSlot.MAINHAND));
|
|
||||||
camera.equipStack(EquipmentSlot.OFFHAND, viewPlayer.getEquippedStack(EquipmentSlot.OFFHAND));
|
|
||||||
//#else
|
|
||||||
//$$ camera.inventory = viewPlayer.inventory;
|
|
||||||
//#endif
|
|
||||||
EntityPlayerAccessor cameraA = (EntityPlayerAccessor) camera;
|
|
||||||
EntityPlayerAccessor viewPlayerA = (EntityPlayerAccessor) viewPlayer;
|
|
||||||
//#if MC>=10904
|
|
||||||
cameraA.setItemStackMainHand(viewPlayerA.getItemStackMainHand());
|
|
||||||
camera.preferredHand = viewPlayer.preferredHand;
|
|
||||||
cameraA.setActiveItemStackUseCount(viewPlayerA.getActiveItemStackUseCount());
|
|
||||||
//#else
|
|
||||||
//$$ cameraA.setItemInUse(viewPlayerA.getItemInUse());
|
|
||||||
//$$ cameraA.setItemInUseCount(viewPlayerA.getItemInUseCount());
|
|
||||||
//#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ public abstract class MixinKeyboardListener {
|
|||||||
//#endif
|
//#endif
|
||||||
at = @At(
|
at = @At(
|
||||||
value = "INVOKE",
|
value = "INVOKE",
|
||||||
//#if MC>=11400
|
//#if MC>=11701
|
||||||
|
//$$ target = "Lnet/minecraft/client/util/ScreenshotRecorder;saveScreenshot(Ljava/io/File;Lnet/minecraft/client/gl/Framebuffer;Ljava/util/function/Consumer;)V"
|
||||||
|
//#elseif MC>=11400
|
||||||
target = "Lnet/minecraft/client/util/ScreenshotUtils;saveScreenshot(Ljava/io/File;IILnet/minecraft/client/gl/Framebuffer;Ljava/util/function/Consumer;)V"
|
target = "Lnet/minecraft/client/util/ScreenshotUtils;saveScreenshot(Ljava/io/File;IILnet/minecraft/client/gl/Framebuffer;Ljava/util/function/Consumer;)V"
|
||||||
//#else
|
//#else
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.replaymod.replay.mixin;
|
|||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
import net.minecraft.client.network.AbstractClientPlayerEntity;
|
||||||
|
import net.minecraft.client.network.OtherClientPlayerEntity;
|
||||||
import net.minecraft.client.network.PlayerListEntry;
|
import net.minecraft.client.network.PlayerListEntry;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
@@ -24,8 +25,19 @@ public abstract class Mixin_FixNPCSkinCaching {
|
|||||||
// intended ones. To fix that, we make this caching-glitch which servers have come to rely on an actual feature
|
// intended ones. To fix that, we make this caching-glitch which servers have come to rely on an actual feature
|
||||||
// by just fetching the cache in the constructor which arguably is what MC should have done to begin with,
|
// by just fetching the cache in the constructor which arguably is what MC should have done to begin with,
|
||||||
// especially because the spawn packet handling code already requires the entry to be present).
|
// especially because the spawn packet handling code already requires the entry to be present).
|
||||||
if (MinecraftClient.getInstance().getNetworkHandler() != null) { // will be null if this is the client player
|
|
||||||
|
// To reduce the chance of incompatibility with custom player entities, we only do this for the vanilla MP one.
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
if (!(((Object) this) instanceof OtherClientPlayerEntity)) return;
|
||||||
|
|
||||||
|
// To get the player list entry, we need to be connected (we usually are, but better be safe than sorry)
|
||||||
|
if (MinecraftClient.getInstance().getNetworkHandler() == null) return;
|
||||||
|
|
||||||
|
// And we catch any exceptions, so if there is still something, it's hopefully not fatal
|
||||||
|
try {
|
||||||
this.getPlayerListEntry();
|
this.getPlayerListEntry();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,9 +150,9 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
|
|||||||
synchronized (replayFile) {
|
synchronized (replayFile) {
|
||||||
Timeline timeline = replayFile.getTimelines(new SPTimeline()).get("");
|
Timeline timeline = replayFile.getTimelines(new SPTimeline()).get("");
|
||||||
if (timeline != null) {
|
if (timeline != null) {
|
||||||
setCurrentTimeline(new SPTimeline(timeline));
|
setCurrentTimeline(new SPTimeline(timeline), false);
|
||||||
} else {
|
} else {
|
||||||
setCurrentTimeline(new SPTimeline());
|
setCurrentTimeline(new SPTimeline(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -225,8 +225,16 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentTimeline(SPTimeline newTimeline) {
|
public void setCurrentTimeline(SPTimeline newTimeline) {
|
||||||
|
setCurrentTimeline(newTimeline, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCurrentTimeline(SPTimeline newTimeline, boolean save) {
|
||||||
selectedPath = null;
|
selectedPath = null;
|
||||||
currentTimeline = newTimeline;
|
currentTimeline = newTimeline;
|
||||||
|
if (!save) {
|
||||||
|
lastTimeline = newTimeline;
|
||||||
|
lastChange = newTimeline.getTimeline().peekUndoStack();
|
||||||
|
}
|
||||||
updateDefaultInterpolatorType();
|
updateDefaultInterpolatorType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,18 +262,21 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
|
|||||||
|
|
||||||
private final AtomicInteger lastSaveId = new AtomicInteger();
|
private final AtomicInteger lastSaveId = new AtomicInteger();
|
||||||
private ExecutorService saveService;
|
private ExecutorService saveService;
|
||||||
|
private SPTimeline lastTimeline;
|
||||||
private Change lastChange;
|
private Change lastChange;
|
||||||
private void maybeSaveTimeline(ReplayFile replayFile) {
|
private void maybeSaveTimeline(ReplayFile replayFile) {
|
||||||
SPTimeline spTimeline = currentTimeline;
|
SPTimeline spTimeline = currentTimeline;
|
||||||
if (spTimeline == null || saveService == null) {
|
if (spTimeline == null || saveService == null) {
|
||||||
|
lastTimeline = null;
|
||||||
lastChange = null;
|
lastChange = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Change latestChange = spTimeline.getTimeline().peekUndoStack();
|
Change latestChange = spTimeline.getTimeline().peekUndoStack();
|
||||||
if (latestChange == null || latestChange == lastChange) {
|
if (spTimeline == lastTimeline && latestChange == lastChange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
lastTimeline = spTimeline;
|
||||||
lastChange = latestChange;
|
lastChange = latestChange;
|
||||||
|
|
||||||
// Clone the timeline for async saving
|
// Clone the timeline for async saving
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import java.util.Optional;
|
|||||||
import static com.replaymod.core.versions.MCVer.emitLine;
|
import static com.replaymod.core.versions.MCVer.emitLine;
|
||||||
import static de.johni0702.minecraft.gui.versions.MCVer.popScissorState;
|
import static de.johni0702.minecraft.gui.versions.MCVer.popScissorState;
|
||||||
import static de.johni0702.minecraft.gui.versions.MCVer.pushScissorState;
|
import static de.johni0702.minecraft.gui.versions.MCVer.pushScissorState;
|
||||||
import static de.johni0702.minecraft.gui.versions.MCVer.setScissorState;
|
import static de.johni0702.minecraft.gui.versions.MCVer.setScissorDisabled;
|
||||||
|
|
||||||
//#if MC>=11700
|
//#if MC>=11700
|
||||||
//$$ import com.mojang.blaze3d.systems.RenderSystem;
|
//$$ import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
@@ -176,7 +176,7 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
|
|||||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||||
//#endif
|
//#endif
|
||||||
pushScissorState();
|
pushScissorState();
|
||||||
setScissorState(false);
|
setScissorDisabled();
|
||||||
GL11.glLineWidth(2);
|
GL11.glLineWidth(2);
|
||||||
tessellator.draw();
|
tessellator.draw();
|
||||||
popScissorState();
|
popScissorState();
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ public class GuiPathing {
|
|||||||
public final GuiButton renderButton = new GuiButton().onClick(new Runnable() {
|
public final GuiButton renderButton = new GuiButton().onClick(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
abortPathPlayback();
|
||||||
GuiScreen screen = GuiRenderSettings.createBaseScreen();
|
GuiScreen screen = GuiRenderSettings.createBaseScreen();
|
||||||
new GuiRenderQueue(screen, replayHandler, () -> preparePathsForPlayback(false)) {
|
new GuiRenderQueue(screen, replayHandler, () -> preparePathsForPlayback(false)) {
|
||||||
@Override
|
@Override
|
||||||
@@ -378,7 +379,21 @@ public class GuiPathing {
|
|||||||
startLoadingEntityTracker();
|
startLoadingEntityTracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void abortPathPlayback() {
|
||||||
|
if (!player.isActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListenableFuture<Void> future = player.getFuture();
|
||||||
|
if (!future.isDone() && !future.isCancelled()) {
|
||||||
|
future.cancel(false);
|
||||||
|
}
|
||||||
|
// Tear down of the player might only happen the next tick after it was cancelled
|
||||||
|
player.onTick();
|
||||||
|
}
|
||||||
|
|
||||||
public void keyframeRepoButtonPressed() {
|
public void keyframeRepoButtonPressed() {
|
||||||
|
abortPathPlayback();
|
||||||
try {
|
try {
|
||||||
GuiKeyframeRepository gui = new GuiKeyframeRepository(
|
GuiKeyframeRepository gui = new GuiKeyframeRepository(
|
||||||
mod.getCurrentTimeline(), replayHandler.getReplayFile(), mod.getCurrentTimeline().getTimeline());
|
mod.getCurrentTimeline(), replayHandler.getReplayFile(), mod.getCurrentTimeline().getTimeline());
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
"AbstractButtonWidgetAccessor",
|
"AbstractButtonWidgetAccessor",
|
||||||
"MixinGameRenderer",
|
"MixinGameRenderer",
|
||||||
"Mixin_HideDynamicResourcePacks",
|
"Mixin_InjectDynamicResourcePacks",
|
||||||
"Mixin_RegisterDynamicResourcePacks",
|
|
||||||
//#endif
|
//#endif
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
"MixinMouse",
|
"MixinMouse",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.6.0
|
2.6.1
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
net.minecraft.item.ItemStack EMPTY field_190927_a
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
net.minecraft.entity.player.PlayerInventory net.minecraft.entity.player.InventoryPlayer
|
||||||
net.minecraft.potion.EffectInstance net.minecraft.potion.PotionEffect
|
net.minecraft.potion.EffectInstance net.minecraft.potion.PotionEffect
|
||||||
net.minecraft.client.gui.screen.AddServerScreen net.minecraft.client.gui.GuiScreenAddServer
|
net.minecraft.client.gui.screen.AddServerScreen net.minecraft.client.gui.GuiScreenAddServer
|
||||||
net.minecraft.resources.AbstractResourcePack net.minecraft.client.resources.AbstractResourcePack
|
net.minecraft.resources.AbstractResourcePack net.minecraft.client.resources.AbstractResourcePack
|
||||||
|
|||||||
Reference in New Issue
Block a user