First Commit
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import scala.actors.threadpool.Arrays;
|
||||
import net.minecraft.entity.DataWatcher;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.Rotations;
|
||||
|
||||
public class LesserDataWatcher extends DataWatcher {
|
||||
|
||||
public LesserDataWatcher(Entity owner) {
|
||||
super(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addObject(int id, Object object) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addObjectByDataType(int id, int type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getWatchableObjectByte(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getWatchableObjectShort(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWatchableObjectInt(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWatchableObjectFloat(int id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWatchableObjectString(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getWatchableObjectItemStack(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rotations getWatchableObjectRotations(int id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObject(int id, Object newData) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setObjectWatched(int id) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasObjectChanged() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List getChanged() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(PacketBuffer buffer) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List getAllWatched() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateWatchedObjectsFromList(List p_75687_1_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsBlank() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_111144_e() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
|
||||
public class OpenEmbeddedChannel extends EmbeddedChannel {
|
||||
|
||||
private boolean ignoreClose = false;
|
||||
|
||||
public OpenEmbeddedChannel(NetworkManager networkManager) {
|
||||
super(networkManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finish() {
|
||||
System.out.println("wanted to finish");
|
||||
ignoreClose = true;
|
||||
return super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture close() {
|
||||
if(ignoreClose) {
|
||||
ignoreClose = false;
|
||||
return null;
|
||||
}
|
||||
return pipeline().close();
|
||||
}
|
||||
|
||||
public ChannelFuture manualClose() {
|
||||
return pipeline().close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import gnu.trove.iterator.TIntObjectIterator;
|
||||
import gnu.trove.map.TIntObjectMap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
import net.minecraft.network.EnumPacketDirection;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.MessageDeserializer;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
|
||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||
|
||||
public class PacketDeserializer extends MessageDeserializer {
|
||||
|
||||
private final EnumPacketDirection direction;
|
||||
private Field directionMaps;
|
||||
private EnumConnectionState state;
|
||||
|
||||
public PacketDeserializer(EnumPacketDirection direction) {
|
||||
super(direction);
|
||||
this.direction = direction;
|
||||
try {
|
||||
directionMaps = EnumConnectionState.class.getDeclaredField(MCPNames.field("field_179247_h"));
|
||||
directionMaps.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Packet getPacket(EnumPacketDirection direction, int packetId) throws InstantiationException, IllegalAccessException
|
||||
{
|
||||
Map map = ((Map)directionMaps.get(state));
|
||||
BiMap biMap = ((BiMap)map.get(direction));
|
||||
if(biMap == null) {
|
||||
System.out.println("BiMap is null!");
|
||||
}
|
||||
Class oclass = (Class)biMap.get(Integer.valueOf(packetId));
|
||||
return oclass == null ? null : (Packet)oclass.newInstance();
|
||||
}
|
||||
|
||||
public void setEnumConnectionState(EnumConnectionState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ChannelHandlerContext p_decode_1_,
|
||||
ByteBuf p_decode_2_, List p_decode_3_) throws IOException,
|
||||
InstantiationException, IllegalAccessException {
|
||||
|
||||
if (p_decode_2_.readableBytes() != 0)
|
||||
{
|
||||
PacketBuffer packetbuffer = new PacketBuffer(p_decode_2_);
|
||||
int i = packetbuffer.readVarIntFromBuffer();
|
||||
|
||||
Field state_by_id = null;
|
||||
try {
|
||||
state_by_id = EnumConnectionState.class.getDeclaredField("STATES_BY_ID"); //TODO: Localize
|
||||
state_by_id.setAccessible(true);
|
||||
state = (EnumConnectionState)((TIntObjectMap)state_by_id.get(null)).get(i);
|
||||
TIntObjectMap map = (TIntObjectMap)state_by_id.get(null);
|
||||
TIntObjectIterator it = map.iterator();
|
||||
while(it.hasNext()) {
|
||||
it.advance();
|
||||
System.out.println(it.key() +" | "+it.value().getClass());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if(state == null) {
|
||||
System.out.println("state is null");
|
||||
}
|
||||
//Packet packet = getPacket(this.direction, i);
|
||||
Packet packet = state.getPacket(EnumPacketDirection.CLIENTBOUND, i);
|
||||
|
||||
if (packet == null)
|
||||
{
|
||||
throw new IOException("Bad packet id " + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.readPacketData(packetbuffer);
|
||||
|
||||
if (packetbuffer.readableBytes() > 0)
|
||||
{
|
||||
throw new IOException("Packet " + ((EnumConnectionState)p_decode_1_.channel().attr(NetworkManager.attrKeyConnectionState).get()).getId() + "/" + i + " (" + packet.getClass().getSimpleName() + ") was larger than I expected, found " + packetbuffer.readableBytes() + " bytes extra whilst reading packet " + i);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_decode_3_.add(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
|
||||
public class PacketInfo {
|
||||
|
||||
private byte[] bytes;
|
||||
private EnumConnectionState connectionState;
|
||||
private int packetID;
|
||||
|
||||
|
||||
|
||||
public PacketInfo(byte[] bytes, EnumConnectionState connectionState,
|
||||
int packetID) {
|
||||
super();
|
||||
this.bytes = bytes;
|
||||
this.connectionState = connectionState;
|
||||
this.packetID = packetID;
|
||||
}
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
public void setBytes(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
public EnumConnectionState getConnectionState() {
|
||||
return connectionState;
|
||||
}
|
||||
public void setConnectionState(EnumConnectionState connectionState) {
|
||||
this.connectionState = connectionState;
|
||||
}
|
||||
public int getPacketID() {
|
||||
return packetID;
|
||||
}
|
||||
public void setPacketID(int packetID) {
|
||||
this.packetID = packetID;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.EnumPacketDirection;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.play.INetHandlerPlayClient;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageRequests;
|
||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
import eu.crushedpixel.replaymod.holders.KeyframeComparator;
|
||||
import eu.crushedpixel.replaymod.holders.PositionKeyframe;
|
||||
import eu.crushedpixel.replaymod.holders.TimeKeyframe;
|
||||
|
||||
public class ReplayHandler {
|
||||
|
||||
private static NetworkManager networkManager;
|
||||
private static Minecraft mc = Minecraft.getMinecraft();
|
||||
private static ReplaySender replaySender;
|
||||
private static OpenEmbeddedChannel channel;
|
||||
|
||||
private static Keyframe selectedKeyframe;
|
||||
|
||||
private static boolean isReplaying = false;
|
||||
|
||||
private static CameraEntity cameraEntity;
|
||||
|
||||
private static List<Keyframe> keyframes = new ArrayList<Keyframe>();
|
||||
|
||||
private static boolean replayActive = false;
|
||||
|
||||
public static long lastExit = 0;
|
||||
|
||||
public static void setReplaying(boolean replaying) {
|
||||
isReplaying = replaying;
|
||||
}
|
||||
|
||||
public static void startPath() {
|
||||
ReplayProcess.startReplayProcess();
|
||||
}
|
||||
|
||||
public static void interruptReplay() {
|
||||
ReplayProcess.stopReplayProcess(false);
|
||||
}
|
||||
|
||||
public static boolean isReplaying() {
|
||||
return isReplaying;
|
||||
}
|
||||
|
||||
public static void setCameraEntity(CameraEntity entity) {
|
||||
if(entity == null) return;
|
||||
cameraEntity = entity;
|
||||
mc.setRenderViewEntity(cameraEntity);
|
||||
}
|
||||
|
||||
public static CameraEntity getCameraEntity() {
|
||||
return cameraEntity;
|
||||
}
|
||||
|
||||
public static int getReplayTime() {
|
||||
if(replaySender != null) {
|
||||
return (int)replaySender.currentTimeStamp();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void sortKeyframes() {
|
||||
Collections.sort(keyframes, new KeyframeComparator());
|
||||
}
|
||||
|
||||
public static void addKeyframe(Keyframe keyframe) {
|
||||
keyframes.add(keyframe);
|
||||
selectKeyframe(keyframe);
|
||||
}
|
||||
|
||||
public static void removeKeyframe(Keyframe keyframe) {
|
||||
keyframes.remove(keyframe);
|
||||
if(keyframe == selectedKeyframe) {
|
||||
selectKeyframe(null);
|
||||
} else {
|
||||
sortKeyframes();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getKeyframeIndex(TimeKeyframe timeKeyframe) {
|
||||
int index = 0;
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(kf == timeKeyframe) return index;
|
||||
else if(kf instanceof TimeKeyframe) index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getKeyframeIndex(PositionKeyframe posKeyframe) {
|
||||
int index = 0;
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(kf == posKeyframe) return index;
|
||||
else if(kf instanceof PositionKeyframe) index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getPosKeyframeCount() {
|
||||
int size = 0;
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(kf instanceof PositionKeyframe) size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public static int getTimeKeyframeCount() {
|
||||
int size = 0;
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(kf instanceof TimeKeyframe) size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public static TimeKeyframe getClosestTimeKeyframeForRealTime(int realTime, int tolerance) {
|
||||
List<TimeKeyframe> found = new ArrayList<TimeKeyframe>();
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(!(kf instanceof TimeKeyframe)) continue;
|
||||
if(Math.abs(kf.getRealTimestamp()-realTime) <= tolerance) {
|
||||
found.add((TimeKeyframe)kf);
|
||||
}
|
||||
}
|
||||
|
||||
TimeKeyframe closest = null;
|
||||
|
||||
for(TimeKeyframe kf : found) {
|
||||
if(closest == null || Math.abs(closest.getTimestamp()-realTime) > Math.abs(kf.getRealTimestamp()-realTime)) {
|
||||
closest = kf;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
public static PositionKeyframe getClosestPlaceKeyframeForRealTime(int realTime, int tolerance) {
|
||||
List<PositionKeyframe> found = new ArrayList<PositionKeyframe>();
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(!(kf instanceof PositionKeyframe)) continue;
|
||||
if(Math.abs(kf.getRealTimestamp()-realTime) <= tolerance) {
|
||||
found.add((PositionKeyframe)kf);
|
||||
}
|
||||
}
|
||||
|
||||
PositionKeyframe closest = null;
|
||||
|
||||
for(PositionKeyframe kf : found) {
|
||||
if(closest == null || Math.abs(closest.getRealTimestamp()-realTime) > Math.abs(kf.getRealTimestamp()-realTime)) {
|
||||
closest = kf;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
public static PositionKeyframe getPreviousPositionKeyframe(int realTime) {
|
||||
if(keyframes.isEmpty()) return null;
|
||||
List<PositionKeyframe> found = new ArrayList<PositionKeyframe>();
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(!(kf instanceof PositionKeyframe)) continue;
|
||||
if(kf.getRealTimestamp() < realTime) {
|
||||
found.add((PositionKeyframe)kf);
|
||||
}
|
||||
}
|
||||
|
||||
if(found.size() > 0)
|
||||
return found.get(found.size()-1); //last element is nearest
|
||||
else return null;
|
||||
}
|
||||
|
||||
public static PositionKeyframe getNextPositionKeyframe(int realTime) {
|
||||
if(keyframes.isEmpty()) return null;
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(!(kf instanceof PositionKeyframe)) continue;
|
||||
if(kf.getRealTimestamp() >= realTime) {
|
||||
return (PositionKeyframe)kf; //first found element is next
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TimeKeyframe getPreviousTimeKeyframe(int realTime) {
|
||||
if(keyframes.isEmpty()) return null;
|
||||
List<TimeKeyframe> found = new ArrayList<TimeKeyframe>();
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(!(kf instanceof TimeKeyframe)) continue;
|
||||
if(kf.getRealTimestamp() < realTime) {
|
||||
found.add((TimeKeyframe)kf);
|
||||
}
|
||||
}
|
||||
|
||||
if(found.size() > 0)
|
||||
return found.get(found.size()-1); //last element is nearest
|
||||
else return null;
|
||||
}
|
||||
|
||||
public static TimeKeyframe getNextTimeKeyframe(int realTime) {
|
||||
if(keyframes.isEmpty()) return null;
|
||||
for(Keyframe kf : keyframes) {
|
||||
if(!(kf instanceof TimeKeyframe)) continue;
|
||||
if(kf.getRealTimestamp() >= realTime) {
|
||||
return (TimeKeyframe)kf; //first found element is next
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Keyframe> getKeyframes() {
|
||||
return new ArrayList<Keyframe>(keyframes);
|
||||
}
|
||||
|
||||
public static void resetKeyframes() {
|
||||
keyframes = new ArrayList<Keyframe>();
|
||||
selectKeyframe(null);
|
||||
}
|
||||
|
||||
public static void setReplayPos(int pos, boolean force) {
|
||||
if(replaySender != null) {
|
||||
replaySender.jumpToTime(pos, force);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isHurrying() {
|
||||
if(replaySender != null) {
|
||||
return replaySender.isHurrying();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getReplayLength() {
|
||||
if(replaySender != null) {
|
||||
return replaySender.replayLength();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static boolean isSelected(Keyframe kf) {
|
||||
return kf == selectedKeyframe;
|
||||
}
|
||||
|
||||
public static void selectKeyframe(Keyframe kf) {
|
||||
selectedKeyframe = kf;
|
||||
sortKeyframes();
|
||||
}
|
||||
|
||||
public static boolean replayActive() {
|
||||
return replayActive;
|
||||
}
|
||||
|
||||
public static boolean isPaused() {
|
||||
if(replaySender != null) {
|
||||
return replaySender.paused();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setSpeed(double d) {
|
||||
if(replaySender != null) {
|
||||
replaySender.setReplaySpeed(d);
|
||||
}
|
||||
}
|
||||
|
||||
public static double getSpeed() {
|
||||
if(replaySender != null) {
|
||||
return replaySender.getReplaySpeed();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void startReplay(File file) throws NoSuchMethodException, SecurityException, NoSuchFieldException {
|
||||
|
||||
ChatMessageRequests.initialize();
|
||||
mc.ingameGUI.getChatGUI().clearChatMessages();
|
||||
resetKeyframes();
|
||||
|
||||
if(replaySender != null) {
|
||||
replaySender.terminateReplay();
|
||||
}
|
||||
|
||||
if(channel != null) {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND);
|
||||
INetHandlerPlayClient pc = new NetHandlerPlayClient(mc, (GuiScreen)null, networkManager, new GameProfile(UUID.randomUUID(), "Player"));
|
||||
networkManager.setNetHandler(pc);
|
||||
|
||||
channel = new OpenEmbeddedChannel(networkManager);
|
||||
|
||||
replaySender = new ReplaySender(file, networkManager);
|
||||
channel.pipeline().addFirst(replaySender);
|
||||
channel.pipeline().fireChannelActive();
|
||||
|
||||
try {
|
||||
ReplayMod.overlay.resetUI();
|
||||
} catch(Exception e) {}
|
||||
|
||||
replayActive = true;
|
||||
}
|
||||
|
||||
public static void restartReplay() {
|
||||
//mc.setRenderViewEntity(mc.thePlayer);
|
||||
mc.ingameGUI.getChatGUI().clearChatMessages();
|
||||
|
||||
if(channel != null) {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND);
|
||||
INetHandlerPlayClient pc = new NetHandlerPlayClient(mc, (GuiScreen)null, networkManager, new GameProfile(UUID.randomUUID(), "Player"));
|
||||
networkManager.setNetHandler(pc);
|
||||
|
||||
EmbeddedChannel channel = new OpenEmbeddedChannel(networkManager);
|
||||
|
||||
channel.pipeline().addFirst(replaySender);
|
||||
channel.pipeline().fireChannelActive();
|
||||
|
||||
ChannelPipeline pipeline = networkManager.channel().pipeline();
|
||||
|
||||
try {
|
||||
ReplayMod.overlay.resetUI();
|
||||
} catch(Exception e) {}
|
||||
|
||||
replayActive = true;
|
||||
}
|
||||
|
||||
public static void endReplay() {
|
||||
if(replaySender != null) {
|
||||
replaySender.terminateReplay();
|
||||
}
|
||||
|
||||
resetKeyframes();
|
||||
|
||||
if(channel != null) {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
replayActive = false;
|
||||
}
|
||||
|
||||
public static Keyframe getSelected() {
|
||||
return selectedKeyframe;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageRequests;
|
||||
import eu.crushedpixel.replaymod.chat.ChatMessageRequests.ChatMessageType;
|
||||
import eu.crushedpixel.replaymod.holders.Keyframe;
|
||||
import eu.crushedpixel.replaymod.holders.Position;
|
||||
import eu.crushedpixel.replaymod.holders.PositionKeyframe;
|
||||
import eu.crushedpixel.replaymod.holders.TimeKeyframe;
|
||||
import eu.crushedpixel.replaymod.interpolation.LinearPoint;
|
||||
import eu.crushedpixel.replaymod.interpolation.LinearTimestamp;
|
||||
import eu.crushedpixel.replaymod.interpolation.SplinePoint;
|
||||
|
||||
public class ReplayProcess {
|
||||
|
||||
private static Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private static long startRealTime;
|
||||
private static int lastRealReplayTime;
|
||||
private static long lastRealTime = 0;
|
||||
|
||||
private static boolean linear = false;
|
||||
|
||||
private static Position lastPosition = null;
|
||||
private static int lastTimestamp = -1;
|
||||
|
||||
private static SplinePoint motionSpline = null;
|
||||
private static LinearPoint motionLinear = null;
|
||||
private static LinearTimestamp timeLinear = null;
|
||||
|
||||
private static double previousReplaySpeed = 0;
|
||||
|
||||
public static void startReplayProcess() {
|
||||
ChatMessageRequests.initialize();
|
||||
if(ReplayHandler.getKeyframes().isEmpty()) {
|
||||
ChatMessageRequests.addChatMessage("No keyframes set!", ChatMessageType.WARNING);
|
||||
return;
|
||||
}
|
||||
startRealTime = System.currentTimeMillis();
|
||||
lastRealTime = startRealTime;
|
||||
lastRealReplayTime = 0;
|
||||
lastTimestamp = -1;
|
||||
lastPosition = null;
|
||||
motionSpline = null;
|
||||
timeLinear = null;
|
||||
linear = ReplayMod.replaySettings.isLinearMovement();
|
||||
ReplayHandler.sortKeyframes();
|
||||
ReplayHandler.setReplaying(true);
|
||||
previousReplaySpeed = ReplayHandler.getSpeed();
|
||||
TimeKeyframe tf = ReplayHandler.getNextTimeKeyframe(-1);
|
||||
if(tf != null) {
|
||||
int ts = tf.getTimestamp();
|
||||
ReplayHandler.setReplayPos(ts, true);
|
||||
}
|
||||
ChatMessageRequests.addChatMessage("Replay started!", ChatMessageType.INFORMATION);
|
||||
}
|
||||
|
||||
public static void stopReplayProcess(boolean finished) {
|
||||
if(finished) ChatMessageRequests.addChatMessage("Replay finished!", ChatMessageType.INFORMATION);
|
||||
else ChatMessageRequests.addChatMessage("Replay stopped!", ChatMessageType.INFORMATION);
|
||||
ReplayHandler.setReplaying(false);
|
||||
ReplayHandler.setSpeed(previousReplaySpeed);
|
||||
ReplayHandler.setSpeed(0);
|
||||
}
|
||||
|
||||
public static void tickReplay() {
|
||||
if(!ReplayHandler.isReplaying()) return;
|
||||
if(ReplayHandler.isHurrying()) {
|
||||
lastRealTime = System.currentTimeMillis();
|
||||
System.out.println("rethurrn");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!linear && motionSpline == null) {
|
||||
//set up spline path
|
||||
motionSpline = new SplinePoint();
|
||||
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
||||
if(kf instanceof PositionKeyframe) {
|
||||
PositionKeyframe pkf = (PositionKeyframe)kf;
|
||||
Position pos = pkf.getPosition();
|
||||
motionSpline.addPoint(pos);
|
||||
}
|
||||
}
|
||||
if(motionSpline.getPoints().size() < 3) linear = true;
|
||||
else motionSpline.calcSpline();
|
||||
|
||||
}
|
||||
if(linear && motionLinear == null) {
|
||||
//set up linear path
|
||||
motionLinear = new LinearPoint();
|
||||
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
||||
if(kf instanceof PositionKeyframe) {
|
||||
PositionKeyframe pkf = (PositionKeyframe)kf;
|
||||
Position pos = pkf.getPosition();
|
||||
motionLinear.addPoint(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(timeLinear == null) {
|
||||
timeLinear = new LinearTimestamp();
|
||||
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
||||
if(kf instanceof TimeKeyframe) {
|
||||
timeLinear.addPoint(((TimeKeyframe)kf).getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for(float x = 0; x <= 1f; x+=0.1) {
|
||||
//timeLinear.getPoint(x);
|
||||
System.out.println(x+" | "+timeLinear.getPoint(x));
|
||||
}
|
||||
*/
|
||||
//System.out.println(timeLinear.getPoint(0));
|
||||
}
|
||||
|
||||
long curTime = System.currentTimeMillis();
|
||||
long timeStep = curTime - lastRealTime;
|
||||
|
||||
int curRealReplayTime = (int)(lastRealReplayTime + timeStep);
|
||||
|
||||
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime);
|
||||
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(curRealReplayTime);
|
||||
|
||||
int lastPosStamp = 0;
|
||||
int nextPosStamp = 0;
|
||||
|
||||
if(nextPos != null || lastPos != null) {
|
||||
if(nextPos != null) {
|
||||
nextPosStamp = nextPos.getRealTimestamp();
|
||||
} else {
|
||||
nextPosStamp = lastPos.getRealTimestamp();
|
||||
}
|
||||
|
||||
if(lastPos != null) {
|
||||
lastPosStamp = lastPos.getRealTimestamp();
|
||||
} else {
|
||||
lastPosStamp = nextPos.getRealTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
TimeKeyframe lastTime = ReplayHandler.getPreviousTimeKeyframe(curRealReplayTime);
|
||||
TimeKeyframe nextTime = ReplayHandler.getNextTimeKeyframe(curRealReplayTime);
|
||||
|
||||
int lastTimeStamp = 0;
|
||||
int nextTimeStamp = 0;
|
||||
|
||||
double curSpeed = 0f;
|
||||
|
||||
if(nextTime != null || lastTime != null) {
|
||||
if(nextTime != null) {
|
||||
nextTimeStamp = nextTime.getRealTimestamp();
|
||||
} else {
|
||||
nextTimeStamp = lastTime.getRealTimestamp();
|
||||
}
|
||||
|
||||
if(lastTime != null) {
|
||||
lastTimeStamp = lastTime.getRealTimestamp();
|
||||
} else {
|
||||
lastTimeStamp = nextTime.getRealTimestamp();
|
||||
}
|
||||
|
||||
if(!(nextTime == null || lastTime == null)) {
|
||||
curSpeed = ((double)((nextTime.getTimestamp()-lastTime.getTimestamp())))/((double)((nextTimeStamp-lastTimeStamp)));
|
||||
}
|
||||
}
|
||||
|
||||
int currentDiff = nextPosStamp - lastPosStamp;
|
||||
int current = curRealReplayTime - lastPosStamp;
|
||||
|
||||
float currentStepPerc = (float)current/(float)currentDiff; //The percentage of the travelled path between the current positions
|
||||
if(Float.isInfinite(currentStepPerc)) currentStepPerc = 0;
|
||||
|
||||
float splinePos = ((float)ReplayHandler.getKeyframeIndex(lastPos) + currentStepPerc)/(float)(ReplayHandler.getPosKeyframeCount()-1);
|
||||
float timePos = ((float)ReplayHandler.getKeyframeIndex(lastTime) + currentStepPerc)/(float)(ReplayHandler.getTimeKeyframeCount()-1);
|
||||
|
||||
Position pos = null;
|
||||
if(!linear) {
|
||||
pos = motionSpline.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
} else {
|
||||
pos = motionLinear.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
}
|
||||
|
||||
//int curPos = timeLinear.getPoint(Math.max(0, Math.min(1, timePos)));
|
||||
|
||||
//set replay speed
|
||||
if(pos != null) ReplayHandler.getCameraEntity().movePath(pos);
|
||||
//System.out.println(curSpeed+" | "+curPos);
|
||||
//ReplayHandler.setSpeed(curSpeed);
|
||||
//System.out.println("sent "+curPos);
|
||||
//ReplayHandler.setReplayPos(curPos, timePos == 0);
|
||||
|
||||
|
||||
//calculate replay speed
|
||||
|
||||
/*
|
||||
int ts = timeLinear.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
if(ts != lastTimestamp) {
|
||||
lastTimestamp = ts;
|
||||
}
|
||||
*/
|
||||
|
||||
//splinePos = (index of last entry + add) / total entries
|
||||
|
||||
|
||||
lastRealReplayTime = curRealReplayTime;
|
||||
lastRealTime = curTime;
|
||||
|
||||
if(splinePos >= 1) stopReplayProcess(true);
|
||||
}
|
||||
}
|
||||
528
src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java
Normal file
528
src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java
Normal file
@@ -0,0 +1,528 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiDownloadTerrain;
|
||||
import net.minecraft.client.particle.EffectRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
import net.minecraft.network.EnumPacketDirection;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.S01PacketJoinGame;
|
||||
import net.minecraft.network.play.server.S02PacketChat;
|
||||
import net.minecraft.network.play.server.S06PacketUpdateHealth;
|
||||
import net.minecraft.network.play.server.S08PacketPlayerPosLook;
|
||||
import net.minecraft.network.play.server.S0BPacketAnimation;
|
||||
import net.minecraft.network.play.server.S0CPacketSpawnPlayer;
|
||||
import net.minecraft.network.play.server.S14PacketEntity;
|
||||
import net.minecraft.network.play.server.S18PacketEntityTeleport;
|
||||
import net.minecraft.network.play.server.S1CPacketEntityMetadata;
|
||||
import net.minecraft.network.play.server.S1DPacketEntityEffect;
|
||||
import net.minecraft.network.play.server.S28PacketEffect;
|
||||
import net.minecraft.network.play.server.S29PacketSoundEffect;
|
||||
import net.minecraft.network.play.server.S2BPacketChangeGameState;
|
||||
import net.minecraft.network.play.server.S2DPacketOpenWindow;
|
||||
import net.minecraft.network.play.server.S2EPacketCloseWindow;
|
||||
import net.minecraft.network.play.server.S2FPacketSetSlot;
|
||||
import net.minecraft.network.play.server.S30PacketWindowItems;
|
||||
import net.minecraft.network.play.server.S36PacketSignEditorOpen;
|
||||
import net.minecraft.network.play.server.S37PacketStatistics;
|
||||
import net.minecraft.network.play.server.S39PacketPlayerAbilities;
|
||||
import net.minecraft.network.play.server.S43PacketCamera;
|
||||
import net.minecraft.network.play.server.S45PacketTitle;
|
||||
import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove;
|
||||
import net.minecraft.util.Timer;
|
||||
import net.minecraft.world.EnumDifficulty;
|
||||
import net.minecraft.world.WorldSettings.GameType;
|
||||
import net.minecraft.world.WorldType;
|
||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||
|
||||
@Sharable
|
||||
public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private long currentTimeStamp;
|
||||
private boolean hurryToTimestamp;
|
||||
private long desiredTimeStamp;
|
||||
private long lastTimeStamp, lastPacketSent;
|
||||
|
||||
private long toleratedTimeStamp;
|
||||
|
||||
private File replayFile;
|
||||
private PacketDeserializer ds = new PacketDeserializer(EnumPacketDirection.SERVERBOUND);
|
||||
private boolean active = true;
|
||||
private ZipFile archive;
|
||||
private DataInputStream dis;
|
||||
private ChannelHandlerContext ctx = null;
|
||||
|
||||
private boolean startFromBeginning = true;
|
||||
|
||||
private NetworkManager networkManager;
|
||||
private boolean terminate = false;
|
||||
|
||||
private float defaultReplaySpeed = 0.5f;
|
||||
|
||||
private int packetAt = 0;
|
||||
private double replaySpeed = 1f;
|
||||
private long lastTime = 0, lastTimestamp = 0;
|
||||
|
||||
private Field joinPacketEntityId, joinPacketWorldType,
|
||||
joinPacketDimension, joinPacketDifficulty, joinPacketMaxPlayers;
|
||||
|
||||
private Field effectPacketEntityId;
|
||||
private Field metadataPacketEntityId, metadataPacketList;
|
||||
|
||||
private Field animationPacketEntityId;
|
||||
private Field entityDataWatcher;
|
||||
|
||||
private Field chatPacketPosition;
|
||||
|
||||
private Minecraft mc = Minecraft.getMinecraft();
|
||||
private Field mcTimer;
|
||||
|
||||
private long now = System.currentTimeMillis();
|
||||
|
||||
private int replayLength = 0;
|
||||
|
||||
private EffectRenderer old = mc.effectRenderer;
|
||||
|
||||
private ZipArchiveEntry replayEntry;
|
||||
|
||||
public boolean isHurrying() {
|
||||
return hurryToTimestamp;
|
||||
}
|
||||
|
||||
public long currentTimeStamp() {
|
||||
return currentTimeStamp;
|
||||
}
|
||||
|
||||
public int replayLength() {
|
||||
return replayLength;
|
||||
}
|
||||
|
||||
public void terminateReplay() {
|
||||
terminate = true;
|
||||
try {
|
||||
channelInactive(ctx);
|
||||
ctx.channel().pipeline().close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void jumpToTime(int millis, boolean forceReload) {
|
||||
setReplaySpeed(replaySpeed);
|
||||
|
||||
if((millis < currentTimeStamp && !isHurrying()) || forceReload) {
|
||||
if(forceReload) System.out.println("forced");
|
||||
if(ReplayHandler.isReplaying()) {
|
||||
if(forceReload) {
|
||||
startFromBeginning = true;
|
||||
}
|
||||
else {
|
||||
startFromBeginning = false;
|
||||
desiredTimeStamp = millis;
|
||||
hurryToTimestamp = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
startFromBeginning = true;
|
||||
}
|
||||
}
|
||||
|
||||
desiredTimeStamp = millis;
|
||||
hurryToTimestamp = true;
|
||||
}
|
||||
|
||||
public void setReplaySpeed(final double d) {
|
||||
if(d != 0) this.replaySpeed = d;
|
||||
|
||||
try {
|
||||
Timer timer = (Timer)mcTimer.get(mc);
|
||||
timer.timerSpeed = (float)d;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ReplaySender(final File replayFile, NetworkManager nm) {
|
||||
try {
|
||||
joinPacketEntityId = S01PacketJoinGame.class.getDeclaredField(MCPNames.field("field_149206_a"));
|
||||
joinPacketEntityId.setAccessible(true);
|
||||
|
||||
joinPacketDifficulty = S01PacketJoinGame.class.getDeclaredField(MCPNames.field("field_149203_e"));
|
||||
joinPacketDifficulty.setAccessible(true);
|
||||
|
||||
joinPacketDimension = S01PacketJoinGame.class.getDeclaredField(MCPNames.field("field_149202_d"));
|
||||
joinPacketDimension.setAccessible(true);
|
||||
|
||||
joinPacketMaxPlayers = S01PacketJoinGame.class.getDeclaredField(MCPNames.field("field_149200_f"));
|
||||
joinPacketMaxPlayers.setAccessible(true);
|
||||
|
||||
joinPacketWorldType = S01PacketJoinGame.class.getDeclaredField(MCPNames.field("field_149201_g"));
|
||||
joinPacketWorldType.setAccessible(true);
|
||||
|
||||
mcTimer = Minecraft.class.getDeclaredField(MCPNames.field("field_71428_T"));
|
||||
mcTimer.setAccessible(true);
|
||||
|
||||
effectPacketEntityId = S1DPacketEntityEffect.class.getDeclaredField(MCPNames.field("field_149434_a"));
|
||||
effectPacketEntityId.setAccessible(true);
|
||||
|
||||
metadataPacketEntityId = S1CPacketEntityMetadata.class.getDeclaredField(MCPNames.field("field_149379_a"));
|
||||
metadataPacketEntityId.setAccessible(true);
|
||||
|
||||
metadataPacketList = S1CPacketEntityMetadata.class.getDeclaredField(MCPNames.field("field_149378_b"));
|
||||
metadataPacketList.setAccessible(true);
|
||||
|
||||
animationPacketEntityId = S0BPacketAnimation.class.getDeclaredField(MCPNames.field("field_148981_a"));
|
||||
animationPacketEntityId.setAccessible(true);
|
||||
|
||||
entityDataWatcher = Entity.class.getDeclaredField(MCPNames.field("field_70180_af"));
|
||||
entityDataWatcher.setAccessible(true);
|
||||
|
||||
chatPacketPosition = S02PacketChat.class.getDeclaredField(MCPNames.field("field_179842_b"));
|
||||
chatPacketPosition.setAccessible(true);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.replayFile = replayFile;
|
||||
this.networkManager = nm;
|
||||
if(("."+FilenameUtils.getExtension(replayFile.getAbsolutePath())).equals(ConnectionEventHandler.ZIP_FILE_EXTENSION)) {
|
||||
try {
|
||||
archive = new ZipFile(replayFile);
|
||||
replayEntry = archive.getEntry("recording"+ConnectionEventHandler.TEMP_FILE_EXTENSION);
|
||||
|
||||
ZipArchiveEntry metadata = archive.getEntry("metaData"+ConnectionEventHandler.JSON_FILE_EXTENSION);
|
||||
InputStream is = archive.getInputStream(metadata);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
String json = br.readLine();
|
||||
|
||||
ReplayMetaData metaData = new Gson().fromJson(json, ReplayMetaData.class);
|
||||
|
||||
this.replayLength = metaData.getDuration();
|
||||
|
||||
sender.start();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Thread sender = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
dis = new DataInputStream(archive.getInputStream(replayEntry));
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
while(ctx == null && !terminate) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
while(!terminate) {
|
||||
if(startFromBeginning) {
|
||||
currentTimeStamp = 0;
|
||||
dis = new DataInputStream(archive.getInputStream(replayEntry));
|
||||
startFromBeginning = false;
|
||||
ReplayHandler.restartReplay();
|
||||
}
|
||||
while(!startFromBeginning && (!paused() || FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class))) {
|
||||
try {
|
||||
|
||||
/*
|
||||
* LOGIC:
|
||||
* While behind desired timestamp, only send packets
|
||||
* until desired timestamp is reached,
|
||||
* then increase desired timestamp by 1/20th of a second
|
||||
*
|
||||
* Desired timestamp is divided through stretch factor.
|
||||
*
|
||||
* If hurrying, don't wait for correct timing.
|
||||
*/
|
||||
|
||||
if(!hurryToTimestamp && ReplayHandler.isReplaying()) {
|
||||
continue;
|
||||
} else if(ReplayHandler.isReplaying()) {
|
||||
System.out.println("nocont "+currentTimeStamp+" | "+((Timer)mcTimer.get(mc)).timerSpeed);
|
||||
}
|
||||
|
||||
int timestamp = dis.readInt();
|
||||
|
||||
currentTimeStamp = timestamp;
|
||||
|
||||
if(!ReplayHandler.isReplaying() && !hurryToTimestamp && !FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class)) {
|
||||
int timeWait = (int)Math.round((currentTimeStamp - lastTimeStamp)/replaySpeed);
|
||||
long timeDiff = System.currentTimeMillis() - lastPacketSent;
|
||||
lastPacketSent = System.currentTimeMillis();
|
||||
Thread.sleep(Math.max(0, timeWait-timeDiff));
|
||||
}
|
||||
|
||||
int bytes = dis.readInt();
|
||||
byte[] bb = new byte[bytes];
|
||||
dis.readFully(bb);
|
||||
|
||||
ReplaySender.this.channelRead(ctx, bb);
|
||||
|
||||
lastTimeStamp = currentTimeStamp;
|
||||
|
||||
if(hurryToTimestamp && currentTimeStamp >= desiredTimeStamp && !startFromBeginning) {
|
||||
toleratedTimeStamp = currentTimeStamp;
|
||||
hurryToTimestamp = false;
|
||||
System.out.println("stop hurrying");
|
||||
}
|
||||
|
||||
} catch(EOFException eof) {
|
||||
setReplaySpeed(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private List<Class> packetClasses = new ArrayList<Class>();
|
||||
|
||||
private static Field field_149074_a; //TODO: REMOVE
|
||||
static {
|
||||
try {
|
||||
field_149074_a = S14PacketEntity.class.getDeclaredField(MCPNames.field("field_149074_a"));
|
||||
field_149074_a.setAccessible(true);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg)
|
||||
throws Exception {
|
||||
if(terminate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(msg instanceof Packet) {
|
||||
super.channelRead(ctx, msg);
|
||||
return;
|
||||
}
|
||||
byte[] ba = (byte[])msg;
|
||||
|
||||
try {
|
||||
ByteBuf bb = Unpooled.buffer(ba.length);
|
||||
PacketBuffer pb = new PacketBuffer(bb);
|
||||
|
||||
pb.writeBytes(ba);
|
||||
|
||||
int i = pb.readVarIntFromBuffer();
|
||||
|
||||
Packet p = EnumConnectionState.PLAY.getPacket(EnumPacketDirection.CLIENTBOUND, i);
|
||||
|
||||
if(hurryToTimestamp) { //If hurrying, ignore some packets
|
||||
if(p instanceof S45PacketTitle ||
|
||||
p instanceof S29PacketSoundEffect) return;
|
||||
}
|
||||
|
||||
if(p instanceof S28PacketEffect) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S2BPacketChangeGameState) { //TODO: Test with rain
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S06PacketUpdateHealth) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S2DPacketOpenWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S2EPacketCloseWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S2FPacketSetSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S30PacketWindowItems) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S36PacketSignEditorOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S02PacketChat) {
|
||||
byte pos = (Byte)chatPacketPosition.get(p);
|
||||
if(pos == 1) { //Ignores command block output sent
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(p instanceof S1CPacketEntityMetadata) {
|
||||
int entityId = (Integer)metadataPacketEntityId.get(p);
|
||||
}
|
||||
|
||||
if(p instanceof S0BPacketAnimation) {
|
||||
int entityId = (Integer)animationPacketEntityId.get(p);
|
||||
if(entityId == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(p instanceof S1DPacketEntityEffect) {
|
||||
int entityId = (Integer)effectPacketEntityId.get(p);
|
||||
if(entityId == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(p instanceof S37PacketStatistics) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
p.readPacketData(pb);
|
||||
|
||||
if(p instanceof S0CPacketSpawnPlayer) {
|
||||
S0CPacketSpawnPlayer sp = (S0CPacketSpawnPlayer)p;
|
||||
System.out.println("PACKET SPAWN PLAYER ----------");
|
||||
System.out.println("ENTITY ID: "+sp.func_148943_d());
|
||||
System.out.println("UUID: "+sp.func_179819_c());
|
||||
System.out.println("X: "+sp.func_148942_f());
|
||||
System.out.println("Y: "+sp.func_148949_g());
|
||||
System.out.println("Z: "+sp.func_148946_h());
|
||||
System.out.println("YAW: "+sp.func_148941_i());
|
||||
System.out.println("PITCH: "+sp.func_148945_j());
|
||||
System.out.println("ITEM: "+sp.func_148947_k());
|
||||
System.out.println("PACKET END -------------------");
|
||||
}
|
||||
|
||||
if(p instanceof S01PacketJoinGame) {
|
||||
|
||||
int entId = (Integer)joinPacketEntityId.get(p);
|
||||
entId = -1;
|
||||
int dimension = (Integer)joinPacketDimension.get(p);
|
||||
EnumDifficulty difficulty = (EnumDifficulty)joinPacketDifficulty.get(p);
|
||||
int maxPlayers = (Integer)joinPacketMaxPlayers.get(p);
|
||||
WorldType worldType = (WorldType)joinPacketWorldType.get(p);
|
||||
|
||||
p = new S01PacketJoinGame(entId, GameType.SPECTATOR, false, dimension,
|
||||
difficulty, maxPlayers, worldType, false);
|
||||
}
|
||||
|
||||
if(p instanceof S39PacketPlayerAbilities) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(p instanceof S08PacketPlayerPosLook) {
|
||||
final S08PacketPlayerPosLook ppl = (S08PacketPlayerPosLook)p;
|
||||
|
||||
if(ReplayHandler.isReplaying()) return;
|
||||
Thread t = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(mc.theWorld == null) {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Entity ent = ReplayHandler.getCameraEntity();
|
||||
if(ent == null || !(ent instanceof CameraEntity)) ent = new CameraEntity(mc.theWorld);
|
||||
CameraEntity cent = (CameraEntity)ent;
|
||||
cent.moveAbsolute(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e());
|
||||
|
||||
ReplayHandler.setCameraEntity(cent);
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
}
|
||||
|
||||
if(p instanceof S43PacketCamera) {
|
||||
return;
|
||||
}
|
||||
if(ReplayHandler.isReplaying())
|
||||
System.out.println("packet arrived");
|
||||
super.channelRead(ctx, p);
|
||||
} catch(Exception e) {
|
||||
System.out.println(p.getClass());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
this.ctx = ctx;
|
||||
networkManager.channel().attr(networkManager.attrKeyConnectionState).set(EnumConnectionState.PLAY);
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
archive.close();
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
public boolean paused() {
|
||||
try {
|
||||
return ((Timer)mcTimer.get(mc)).timerSpeed == 0;
|
||||
} catch(Exception e) {}
|
||||
return true;
|
||||
}
|
||||
|
||||
public double getReplaySpeed() {
|
||||
if(!paused()) return replaySpeed;
|
||||
else return 0;
|
||||
//return timeInfo.get().getSpeed();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user