diff --git a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java index 8878fba2..13fbfabc 100644 --- a/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java +++ b/src/main/java/eu/crushedpixel/replaymod/ReplayMod.java @@ -24,6 +24,16 @@ public class ReplayMod //TODO: Set ReplayHandler replaying to false when replay is exited + //XXX + //Known Bugs + // + //Keyframe removal doesn't seem to properly work + // + // + // + // + + public static final String MODID = "replaymod"; public static final String VERSION = "0.0.1"; @@ -32,6 +42,8 @@ public class ReplayMod public static ReplaySettings replaySettings = new ReplaySettings(0, true, true, true, false); public static Configuration config; + public static RecordingHandler recordingHandler; + public static int PLAYER_ID = -1; // The instance of your mod that Forge uses. @@ -62,9 +74,9 @@ public class ReplayMod FMLCommonHandler.instance().bus().register(tickHandler); MinecraftForge.EVENT_BUS.register(tickHandler); - RecordingHandler rh = new RecordingHandler(); - FMLCommonHandler.instance().bus().register(rh); - MinecraftForge.EVENT_BUS.register(rh); + recordingHandler = new RecordingHandler(); + FMLCommonHandler.instance().bus().register(recordingHandler); + MinecraftForge.EVENT_BUS.register(recordingHandler); } @EventHandler diff --git a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java b/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java index b5f7b781..511e49b1 100644 --- a/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java +++ b/src/main/java/eu/crushedpixel/replaymod/entities/CameraEntity.java @@ -39,9 +39,13 @@ public class CameraEntity extends Entity { mc.thePlayer.rotationYaw = ReplayHandler.getCameraEntity().rotationYaw; //removes water/suffocation/shadow overlays in screen - mc.thePlayer.posX = 0; - mc.thePlayer.posY = 500; - mc.thePlayer.posZ = 0; + //mc.thePlayer.posX = 0; + //mc.thePlayer.posY = 500; + //mc.thePlayer.posZ = 0; + + mc.thePlayer.posX = ReplayHandler.getCameraEntity().posX; + mc.thePlayer.posY = ReplayHandler.getCameraEntity().posY; + mc.thePlayer.posZ = ReplayHandler.getCameraEntity().posZ; } if(direction == null || motion < 0.1) { diff --git a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java index 0ae72bc8..2d8fed11 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/GuiReplayOverlay.java @@ -15,8 +15,10 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.GuiIngameForge; import net.minecraftforge.client.event.MouseEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.event.RenderHandEvent; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.fml.client.FMLClientHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -82,6 +84,13 @@ public class GuiReplayOverlay extends Gui { } catch(Exception e) {} } + @SubscribeEvent + public void renderHand(RenderHandEvent event) { + if(ReplayHandler.replayActive()) { + event.setCanceled(true); + } + } + @SubscribeEvent public void tick(TickEvent event) { if(!ReplayHandler.replayActive()) return; @@ -114,7 +123,12 @@ public class GuiReplayOverlay extends Gui { @SubscribeEvent public void onRenderGui(RenderGameOverlayEvent.Post event) throws IllegalArgumentException, IllegalAccessException { - if(!ReplayHandler.replayActive()) return; + if(!ReplayHandler.replayActive()) { + GuiIngameForge.renderExperiance = true; + return; + } + + GuiIngameForge.renderExperiance = false; GL11.glEnable(GL11.GL_BLEND); drawBlockOutline.set(Minecraft.getMinecraft().entityRenderer, false); @@ -289,7 +303,10 @@ public class GuiReplayOverlay extends Gui { Mouse.setCursorPosition(width/2, height/2); } - speedSlider.drawButton(mc, mouseX, mouseY); + try { + speedSlider.drawButton(mc, mouseX, mouseY); + } catch(Exception e) {} + GlStateManager.resetColor(); Entity player = ReplayHandler.getCameraEntity(); diff --git a/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java index 23336272..601a71aa 100644 --- a/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/RecordingHandler.java @@ -26,86 +26,109 @@ import eu.crushedpixel.replaymod.recording.ConnectionEventHandler; public class RecordingHandler { private Minecraft mc = Minecraft.getMinecraft(); - - private int entityID = Integer.MAX_VALUE; - + + private int entityID = Integer.MIN_VALUE+9001; + @SubscribeEvent public void onPlayerJoin(EntityJoinWorldEvent e) throws IOException { if(e.entity != mc.thePlayer) return; if(!ConnectionEventHandler.isRecording()) return; - + EntityPlayer player = (EntityPlayer)e.entity; - + S38PacketPlayerListItem ppli = new S38PacketPlayerListItem(); ByteBuf buf = Unpooled.buffer(); PacketBuffer pbuf = new PacketBuffer(buf); - + pbuf.writeEnumValue(Action.ADD_PLAYER); pbuf.writeVarIntToBuffer(1); pbuf.writeUuid(e.entity.getUniqueID()); - + pbuf.writeString(player.getName()); pbuf.writeVarIntToBuffer(0); pbuf.writeVarIntToBuffer(mc.playerController.getCurrentGameType().getID()); pbuf.writeVarIntToBuffer(0); - + pbuf.writeBoolean(true); pbuf.writeChatComponent(player.getDisplayName()); - + ppli.readPacketData(pbuf); ConnectionEventHandler.insertPacket(ppli); - - //Packet packet = new S0CPacketSpawnPlayer((EntityPlayer)e.entity); - Packet packet = new S0CPacketSpawnPlayer(); - + + S0CPacketSpawnPlayer packet = new S0CPacketSpawnPlayer(); + ByteBuf bb = Unpooled.buffer(); PacketBuffer pb = new PacketBuffer(bb); - + pb.writeVarIntToBuffer(entityID); - //pb.writeUuid((e.entity).getUniqueID()); pb.writeUuid(e.entity.getUniqueID()); - + pb.writeInt(MathHelper.floor_double(e.entity.posX * 32.0D)); pb.writeInt(MathHelper.floor_double(e.entity.posY * 32.0D)); pb.writeInt(MathHelper.floor_double(e.entity.posZ * 32.0D)); pb.writeByte((byte)((int)(((EntityPlayer)e.entity).rotationYaw * 256.0F / 360.0F))); pb.writeByte((byte)((int)(((EntityPlayer)e.entity).rotationPitch * 256.0F / 360.0F))); - + ItemStack itemstack = ((EntityPlayer)e.entity).inventory.getCurrentItem(); pb.writeInt(itemstack == null ? 0 : Item.getIdFromItem(itemstack.getItem())); ((EntityPlayer)e.entity).getDataWatcher().writeTo(pb); - + packet.readPacketData(pb); - + ConnectionEventHandler.insertPacket(packet); } + private Double lastX = null, lastY = null, lastZ = null; + + public void resetLastPositions() { + lastX = lastY = lastZ = null; + } + @SubscribeEvent public void onPlayerTick(PlayerTickEvent e) { if(e.player != mc.thePlayer) return; if(!ConnectionEventHandler.isRecording()) return; + + boolean force = false; + if(lastX == null || lastY == null || lastZ == null) { + force = true; + lastX = e.player.posX; + lastY = e.player.posY; + lastZ = e.player.posZ; + } - double dx = e.player.prevPosX - e.player.posX; - double dy = e.player.prevPosY - e.player.posY; - double dz = e.player.prevPosZ - e.player.posZ; + double dx = e.player.posX - lastX; + double dy = e.player.posY - lastY; + double dz = e.player.posZ - lastZ; - Packet packet; - if(Math.abs(dx) > 4.0 || Math.abs(dy) > 4.0 || Math.abs(dz) > 4.0) { - packet = new S18PacketEntityTeleport(e.player); + lastX = e.player.posX; + lastY = e.player.posY; + lastZ = e.player.posZ; + + Packet packet = null; + if(force || Math.abs(dx) > 4.0 || Math.abs(dy) > 4.0 || Math.abs(dz) > 4.0) { + int x = MathHelper.floor_double(e.player.posX * 32.0D); + int y = MathHelper.floor_double(e.player.posY * 32.0D); + int z = MathHelper.floor_double(e.player.posZ * 32.0D); + byte yaw = (byte)((int)(e.player.rotationYaw * 256.0F / 360.0F)); + byte pitch = (byte)((int)(e.player.rotationPitch * 256.0F / 360.0F)); + packet = new S18PacketEntityTeleport(entityID, x, y, z, yaw, pitch, e.player.onGround); + } else { byte oldYaw = (byte)((int)(e.player.prevRotationYaw * 256.0F / 360.0F)); byte newYaw = (byte)((int)(e.player.rotationYaw * 256.0F / 360.0F)); byte oldPitch = (byte)((int)(e.player.prevRotationPitch * 256.0F / 360.0F)); byte newPitch = (byte)((int)(e.player.rotationPitch * 256.0F / 360.0F)); - + byte dPitch = (byte)(newPitch-oldPitch); byte dYaw = (byte)(newYaw-oldYaw); - + packet = new S17PacketEntityLookMove(entityID, (byte)Math.round(dx*32), (byte)Math.round(dy*32), (byte)Math.round(dz*32), dYaw, dPitch, e.player.onGround); } - - ConnectionEventHandler.insertPacket(packet); + if(packet != null) { + ConnectionEventHandler.insertPacket(packet); + } } } diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java index 8ac37d58..e6137d10 100644 --- a/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/recording/ConnectionEventHandler.java @@ -50,7 +50,7 @@ public class ConnectionEventHandler { return; } try { - packetListener.channelRead(null, packet); + packetListener.saveOnly(packet); } catch (Exception e) { e.printStackTrace(); } @@ -61,6 +61,8 @@ public class ConnectionEventHandler { System.out.println("Connected to server"); ChatMessageRequests.initialize(); + + ReplayMod.recordingHandler.resetLastPositions(); try { if(event.isLocal) { diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java b/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java index 07d528b4..b1f88fd3 100644 --- a/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java +++ b/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java @@ -6,6 +6,7 @@ import io.netty.channel.ChannelHandlerContext; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.lang.reflect.Field; import net.minecraft.entity.DataWatcher; @@ -28,6 +29,17 @@ public class PacketListener extends DataListener { private static final PacketSerializer packetSerializer = new PacketSerializer(EnumPacketDirection.CLIENTBOUND); + public void saveOnly(Packet packet) { + try { + PacketData pd = getPacketData(context, packet); + dataWriter.writeData(pd); + lastSentPacket = pd.getTimestamp(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if(ctx == null) { @@ -45,52 +57,10 @@ public class PacketListener extends DataListener { if(msg instanceof Packet) { try { Packet packet = (Packet)msg; - - if(startTime == null) startTime = System.currentTimeMillis(); - - int timestamp = (int)(System.currentTimeMillis() - startTime); - //Converts the packet back to a ByteBuffer for correct saving - - ByteBuf bb = Unpooled.buffer(); - if(packet instanceof S0FPacketSpawnMob) { - Field field_149043_l = S0FPacketSpawnMob.class.getDeclaredField(MCPNames.field("field_149043_l")); - field_149043_l.setAccessible(true); - DataWatcher l = (DataWatcher)field_149043_l.get(packet); - DataWatcher dw = new DataWatcher(null); - if(l == null) { - field_149043_l.set(packet, dw); - } - } - - if(packet instanceof S0CPacketSpawnPlayer) { - Field field_149043_l = S0CPacketSpawnPlayer.class.getDeclaredField(MCPNames.field("field_148960_i")); - field_149043_l.setAccessible(true); - DataWatcher l = (DataWatcher)field_149043_l.get(packet); - DataWatcher dw = new DataWatcher(null); - if(l == null) { - field_149043_l.set(packet, dw); - } - } - - packetSerializer.encode(ctx, packet, bb); - - bb.readerIndex(0); - byte[] array = new byte[bb.readableBytes()]; - bb.readBytes(array); - - totalBytes += (array.length + (2*4)); //two Integer values and the Packet size - if(totalBytes >= maxSize && maxSize > 0) { - ChatMessageRequests.addChatMessage("Maximum file size exceeded", ChatMessageType.WARNING); - ChatMessageRequests.addChatMessage("The Recording has been stopped", ChatMessageType.WARNING); - alive = false; - } - - bb.readerIndex(0); - - dataWriter.writeData(new PacketData(array, timestamp)); - - lastSentPacket = timestamp; + PacketData pd = getPacketData(ctx, packet); + dataWriter.writeData(pd); + lastSentPacket = pd.getTimestamp(); } catch(Exception e) { e.printStackTrace(); } @@ -99,5 +69,52 @@ public class PacketListener extends DataListener { super.channelRead(ctx, msg); } + + private PacketData getPacketData(ChannelHandlerContext ctx, Packet packet) throws IOException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + + if(startTime == null) startTime = System.currentTimeMillis(); + + int timestamp = (int)(System.currentTimeMillis() - startTime); + + //Converts the packet back to a ByteBuffer for correct saving + + ByteBuf bb = Unpooled.buffer(); + if(packet instanceof S0FPacketSpawnMob) { + Field field_149043_l = S0FPacketSpawnMob.class.getDeclaredField(MCPNames.field("field_149043_l")); + field_149043_l.setAccessible(true); + DataWatcher l = (DataWatcher)field_149043_l.get(packet); + DataWatcher dw = new DataWatcher(null); + if(l == null) { + field_149043_l.set(packet, dw); + } + } + + if(packet instanceof S0CPacketSpawnPlayer) { + Field field_149043_l = S0CPacketSpawnPlayer.class.getDeclaredField(MCPNames.field("field_148960_i")); + field_149043_l.setAccessible(true); + DataWatcher l = (DataWatcher)field_149043_l.get(packet); + DataWatcher dw = new DataWatcher(null); + if(l == null) { + field_149043_l.set(packet, dw); + } + } + + packetSerializer.encode(ctx, packet, bb); + + bb.readerIndex(0); + byte[] array = new byte[bb.readableBytes()]; + bb.readBytes(array); + + totalBytes += (array.length + (2*4)); //two Integer values and the Packet size + if(totalBytes >= maxSize && maxSize > 0) { + ChatMessageRequests.addChatMessage("Maximum file size exceeded", ChatMessageType.WARNING); + ChatMessageRequests.addChatMessage("The Recording has been stopped", ChatMessageType.WARNING); + alive = false; + } + + bb.readerIndex(0); + + return new PacketData(array, timestamp); + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index 6e479ac7..43bdeeaf 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -229,18 +229,13 @@ public class ReplayHandler { public static void resetKeyframes() { keyframes = new ArrayList(); + selectKeyframe(null); } public static void setReplayPos(int pos) { if(replaySender != null) { - replaySender.jumpToTime(pos, false); - } - } - - public static void forceReplayPos(int pos) { - if(replaySender != null) { - replaySender.jumpToTime(pos, true); + replaySender.jumpToTime(pos); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java index 83fe0024..0bb34dd4 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayProcess.java @@ -56,7 +56,7 @@ public class ReplayProcess { if(ts < ReplayHandler.getReplayTime()) { mc.displayGuiScreen((GuiScreen)null); } - ReplayHandler.forceReplayPos(ts); + ReplayHandler.setReplayPos(ts); } ChatMessageRequests.addChatMessage("Replay started!", ChatMessageType.INFORMATION); @@ -69,7 +69,7 @@ public class ReplayProcess { ReplayHandler.setSpeed(previousReplaySpeed); ReplayHandler.setSpeed(0); } - + public static void tickReplay() { if(ReplayHandler.isHurrying()) { lastRealTime = System.currentTimeMillis(); @@ -128,7 +128,7 @@ public class ReplayProcess { PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(curRealReplayTime); ReplayHandler.setRealTimelineCursor(curRealReplayTime); - + int lastPosStamp = 0; int nextPosStamp = 0; @@ -188,28 +188,19 @@ public class ReplayProcess { 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); - - - //calculate replay speed - - /* - int ts = timeLinear.getPoint(Math.max(0, Math.min(1, splinePos))); - if(ts != lastTimestamp) { - lastTimestamp = ts; + Integer curPos = null; + if(timeLinear != null) { + curPos = timeLinear.getPoint(Math.max(0, Math.min(1, timePos))); } - */ + + if(pos != null) ReplayHandler.getCameraEntity().movePath(pos); + + ReplayHandler.setSpeed(curSpeed); + + if(curPos != null) ReplayHandler.setReplayPos(curPos); //splinePos = (index of last entry + add) / total entries - lastRealReplayTime = curRealReplayTime; lastRealTime = curTime; diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java index 4e8b00fa..fb55d716 100644 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java @@ -20,6 +20,7 @@ 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.entity.player.EntityPlayer; import net.minecraft.network.EnumConnectionState; import net.minecraft.network.EnumPacketDirection; import net.minecraft.network.NetworkManager; @@ -30,11 +31,10 @@ 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.S1FPacketSetExperience; import net.minecraft.network.play.server.S28PacketEffect; import net.minecraft.network.play.server.S29PacketSoundEffect; import net.minecraft.network.play.server.S2BPacketChangeGameState; @@ -48,13 +48,11 @@ 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.S48PacketResourcePackSend; -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; @@ -75,6 +73,10 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { private long desiredTimeStamp; private long lastTimeStamp, lastPacketSent; + private boolean hasRestarted = false; + + private long toleratedTimeStamp = Long.MAX_VALUE; + private File replayFile; private PacketDeserializer ds = new PacketDeserializer(EnumPacketDirection.SERVERBOUND); private boolean active = true; @@ -87,8 +89,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { private NetworkManager networkManager; private boolean terminate = false; - private float defaultReplaySpeed = 0.5f; - private double replaySpeed = 1f; private Field joinPacketEntityId, joinPacketWorldType, @@ -135,13 +135,16 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { } } - public void jumpToTime(int millis, boolean force) { + public void jumpToTime(int millis) { setReplaySpeed(replaySpeed); if((millis < currentTimeStamp && !isHurrying())) { - if(!(ReplayHandler.isReplaying() && !force)) { - startFromBeginning = true; + if(ReplayHandler.isReplaying()) { + if(millis < toleratedTimeStamp) { + return; + } } + startFromBeginning = true; } desiredTimeStamp = millis; @@ -244,6 +247,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { } while(!terminate) { if(startFromBeginning) { + hasRestarted = true; currentTimeStamp = 0; dis.close(); dis = new DataInputStream(archive.getInputStream(replayEntry)); @@ -265,17 +269,17 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { * If hurrying, don't wait for correct timing. */ - + if(!hurryToTimestamp && ReplayHandler.isReplaying()) { continue; } - + int timestamp = dis.readInt(); currentTimeStamp = timestamp; if(!ReplayHandler.isReplaying() && !hurryToTimestamp && !FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class)) { - //if(!hurryToTimestamp && !FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class)) { + //if(!hurryToTimestamp && !FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class)) { int timeWait = (int)Math.round((currentTimeStamp - lastTimeStamp)/replaySpeed); long timeDiff = System.currentTimeMillis() - lastPacketSent; lastPacketSent = System.currentTimeMillis(); @@ -291,11 +295,23 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { lastTimeStamp = currentTimeStamp; + if(ReplayHandler.isReplaying()) { + toleratedTimeStamp = lastTimeStamp; + } else { + toleratedTimeStamp = -1; + } + if(hurryToTimestamp && currentTimeStamp >= desiredTimeStamp && !startFromBeginning) { hurryToTimestamp = false; + if(!ReplayHandler.isReplaying() || hasRestarted) { + ((Timer)mcTimer.get(mc)).elapsedPartialTicks = 5; + ((Timer)mcTimer.get(mc)).elapsedTicks = 5; + ((Timer)mcTimer.get(mc)).renderPartialTicks = 5; + } if(!ReplayHandler.isReplaying()) { setReplaySpeed(0); } + hasRestarted = false; } } catch(EOFException eof) { @@ -321,6 +337,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { add(S30PacketWindowItems.class); add(S36PacketSignEditorOpen.class); add(S37PacketStatistics.class); + add(S1FPacketSetExperience.class); + add(S43PacketCamera.class); + add(S39PacketPlayerAbilities.class); } }; @@ -391,8 +410,13 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { difficulty, maxPlayers, worldType, false); } - if(p instanceof S39PacketPlayerAbilities) { - return; + if(p instanceof S18PacketEntityTeleport) { + //System.out.println(((S18PacketEntityTeleport) p).func_149449_d()); + if(mc.theWorld != null) { + for(EntityPlayer ep : (List)mc.theWorld.playerEntities) { + System.out.println(ep.posX+" "+ep.posY+" "+ep.posZ); + } + } } if(p instanceof S08PacketPlayerPosLook) {