Files
ReplayModCinematic/src/main/java/com/replaymod/pathing/player/AbstractTimelinePlayer.java
johni0702 165861764c Merge branch '1.8' into 1.9.4
0db1b9e Fix opening a replay multiple times by quickly double clicking (fixes #25)
9ff767b Fix spectated player having the arm model of the camera player
d82cef3 Make sure video folder exists before rendering (fixes #24)
cc65b26 Replace custom update system with forge update checker
c8b71dc Add tooltips to ingame buttons
b240f8a Fix camera path always playing from the beginning regardless of ctrl key
4805e5e Fix crash when setting two keyframes to the same time via the edit keyframe gui
18f8303 Fix crash when moving the last keyframe
fcd4c07 Add error popup when trying to play path with reversed time keyframes Update jGui
9c605ba Update jGui Fix handling of ESC key in popups (fixes #17)
721fdc4 Allow moving the keyframe timeline cursor by dragging (fixes #18)
1851e97 Allow deletion of selected keyframes by pressing the DELETE key (fixes #19)
d547098 Fix markers not being removed
b2c7faa Fix marker not being deselected when clicking anywhere else
4e6b387 Update jGui Fix popups being drawn outside of the actually visible element (fixes #21)
21bbeb2 Fix bitrate field always being active regardless of selected preset (fixes #20)
b5a6d8b Fix camera player head being visible while in third person
dd0537b Center star between resolution fields in render settings gui
e35bfca Increase spacing between rows in the render settings gui
6d0cdfb Update jGui (fixes #15)
2016-11-10 21:02:55 +01:00

124 lines
4.2 KiB
Java

package com.replaymod.pathing.player;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Longs;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.replaymod.replay.ReplayHandler;
import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Path;
import com.replaymod.replaystudio.pathing.path.Timeline;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import javax.annotation.Nullable;
import java.util.Iterator;
/**
* Plays a timeline.
*/
public abstract class AbstractTimelinePlayer {
private final Minecraft mc = Minecraft.getMinecraft();
private final ReplayHandler replayHandler;
private Timeline timeline;
protected long startOffset;
private long lastTime;
private long lastTimestamp;
private ListenableFuture<Void> future;
private SettableFuture<Void> settableFuture;
public AbstractTimelinePlayer(ReplayHandler replayHandler) {
this.replayHandler = replayHandler;
}
public ListenableFuture<Void> start(Timeline timeline, long from) {
startOffset = from;
return start(timeline);
}
public ListenableFuture<Void> start(Timeline timeline) {
this.timeline = timeline;
Iterator<Keyframe> iter = Iterables.concat(Iterables.transform(timeline.getPaths(),
new Function<Path, Iterable<Keyframe>>() {
@Nullable
@Override
public Iterable<Keyframe> apply(@Nullable Path input) {
assert input != null;
return input.getKeyframes();
}
})).iterator();
if (!iter.hasNext()) {
lastTimestamp = 0;
} else {
lastTimestamp = new Ordering<Keyframe>() {
@Override
public int compare(@Nullable Keyframe left, @Nullable Keyframe right) {
assert left != null;
assert right != null;
return Longs.compare(left.getTime(), right.getTime());
}
}.max(iter).getTime();
}
replayHandler.getReplaySender().setSyncModeAndWait();
MinecraftForge.EVENT_BUS.register(this);
lastTime = 0;
mc.timer = new ReplayTimer(mc.timer);
mc.timer.timerSpeed = 1;
mc.timer.elapsedPartialTicks = mc.timer.elapsedTicks = 0;
return future = settableFuture = SettableFuture.create();
}
public ListenableFuture<Void> getFuture() {
return future;
}
public boolean isActive() {
return future != null && !future.isDone();
}
@SubscribeEvent
public void onTick(ReplayTimer.UpdatedEvent event) {
if (future.isDone()) {
mc.timer = ((ReplayTimer) mc.timer).getWrapped();
replayHandler.getReplaySender().setReplaySpeed(0);
replayHandler.getReplaySender().setAsyncMode(true);
MinecraftForge.EVENT_BUS.unregister(this);
return;
}
long time = getTimePassed();
if (time > lastTimestamp) {
time = lastTimestamp;
}
// Apply to timeline
timeline.applyToGame(time, replayHandler);
// Update minecraft timer
long replayTime = replayHandler.getReplaySender().currentTimeStamp();
if (lastTime == 0) {
// First frame, no change yet
lastTime = replayTime;
}
float timeInTicks = replayTime / 50f;
float previousTimeInTicks = lastTime / 50f;
float passedTicks = timeInTicks - previousTimeInTicks;
mc.timer.elapsedPartialTicks += passedTicks;
mc.timer.elapsedTicks = (int) mc.timer.elapsedPartialTicks;
mc.timer.elapsedPartialTicks -= mc.timer.elapsedTicks;
mc.timer.renderPartialTicks = mc.timer.elapsedPartialTicks;
lastTime = replayTime;
if (time >= lastTimestamp) {
settableFuture.set(null);
}
}
public abstract long getTimePassed();
}