private void PlaybackRecv() { try { NetworkStream nstream = TcpClientLocal.GetStream(); int connection = 0; bool doLoop = true, obtainedXteaKey = false; while (doLoop) { Objects.Packet p = Objects.Packet.GetNextPacket(nstream); if (p.Length == 0) { break; } if (!obtainedXteaKey) { if (Client.TibiaVersion >= 770) { this.XteaKey = new uint[4]; for (int i = 0; i < 4; i++) { this.XteaKey[i] = Memory.ReadUInt(Addresses.Client.XTEAKey + i * 4); } } obtainedXteaKey = true; } connection = Memory.ReadByte(Addresses.Client.Connection); switch ((Enums.Connection)connection) { case Enums.Connection.WaitingForCharacterList: if (this.AutoPlayback) { p = new Objects.Packet(); p.AddByte(0x64); p.AddByte(1); p.AddString("TibiaCam"); p.AddString(CurrentRecording.TibiaVersion); p.AddBytes(IPAddress.Loopback.GetAddressBytes()); p.AddUInt16(this.ListenerPort); p.AddUInt16(0); // premium days p.AddLength(); if (Client.TibiaVersion >= 770) { p.XteaEncrypt(this.XteaKey); p.AddLength(); } p.Send(this.TcpClientLocal); doLoop = false; break; } List <string> files = new List <string>(); foreach (string kcam in System.IO.Directory.GetFiles(System.Windows.Forms.Application.StartupPath + "\\", "*.kcam")) { files.Add(kcam); } foreach (string iryontcam in System.IO.Directory.GetFiles(System.Windows.Forms.Application.StartupPath + "\\", "*.cam")) { files.Add(iryontcam); } if (Settings.Tibiacam.Playback.SupportTibiaMovies) { foreach (string tmv in System.IO.Directory.GetFiles(System.Windows.Forms.Application.StartupPath + "\\", "*.tmv")) { files.Add(tmv); } } files.Sort(); string warning = string.Empty; int count = files.Count; if (files.Count > 255) { warning = "\n\nWarning! There are " + files.Count + " recordings.\nOnly the first 255 recordings are listed."; count = 255; } p = new Objects.Packet(); p.AddByte(0x14); // motd type // motd id is 0-255, which is followed by a newline (\n) p.AddString((byte)new Random().Next(255) + "\nThank you for using Tibianic Tools.\nhttp://code.google.com/p/tibianic-tools/\nhttp://tibianic.org/" + warning); p.AddByte(0x64); // character list type List <Recording> recordings = new List <Recording>(); for (int i = 0; i < count; i++) { Recording r = new Recording(files[i], Settings.Tibiacam.Playback.ReadMetaData, false, false); if (!r.isCorrupt) { recordings.Add(r); } } p.AddByte((byte)count); // amount of characters foreach (Recording r in recordings) { p.AddString(r.FileNameShort); // character name p.AddString(r.TibiaVersion); // server name p.AddBytes(IPAddress.Loopback.GetAddressBytes()); // server ipv4 (in this case: 127.0.0.1) p.AddUInt16(this.ListenerPort); // server port } p.AddUInt16((ushort)count); // premium days p.AddLength(); if (Client.TibiaVersion >= 770) { p.XteaEncrypt(this.XteaKey); p.AddLength(); } p.Send(TcpClientLocal); doLoop = false; break; case Enums.Connection.ConnectingGameServer: if (this.AutoPlayback) { this.threadPlaybackSend = new Thread(new ThreadStart(PlaybackSend)); this.threadPlaybackSend.Start(); break; } CharacterList.Player player = CharacterList.GetPlayers()[Memory.ReadByte(Addresses.Charlist.SelectedIndex)]; if (!System.IO.File.Exists(player.Name)) { System.Windows.Forms.MessageBox.Show(player.Name + "\ndoes not exist", "Error"); doLoop = false; break; } Recording rec = new Recording(player.Name, true, true, Settings.Tibiacam.Playback.doPlayMouse); if (rec.isCorrupt || !rec.ContainsData()) { System.Windows.Forms.MessageBox.Show(player.Name + "\nappears to be corrupt or it doesn't contain any data", "Error"); doLoop = false; break; } this.CurrentRecording = rec; while (this.threadPlaybackSend != null && this.threadPlaybackSend.IsAlive) { this.threadPlaybackSend.Abort(); Thread.Sleep(100); } while (this.threadPlaybackSendMouse != null && this.threadPlaybackSendMouse.IsAlive) { this.threadPlaybackSendMouse.Abort(); Thread.Sleep(100); } this.threadPlaybackSend = new Thread(new ThreadStart(PlaybackSend)); this.threadPlaybackSend.Start(); break; case Enums.Connection.Online: ushort len = p.GetUInt16(); if (Client.TibiaVersion >= 770) { p = p.XteaDecrypt(this.XteaKey, 2); if (p == null) { break; } p.GetPosition = 2; } byte type = p.GetByte(); switch (type) { case 0x14: // logout while (this.threadPlaybackSend != null && this.threadPlaybackSend.IsAlive) { this.threadPlaybackSend.Abort(); Thread.Sleep(100); } this.TcpClientLocal.Close(); return; case 0x96: // player speech byte speechType = p.GetByte(); if (speechType < 1 || speechType > 3) { break; } string msg = p.GetString().ToLower(); string[] msgSplit = msg.Split(' '); p = new Objects.Packet(); switch (msgSplit[0]) { case "info": p.AddByte(0xb4); p.AddByte(22); p.AddString("Tibia version: " + this.CurrentRecording.TibiaVersion + "\nRecorder version: " + this.CurrentRecording.RecorderVersion + "\n# of packets: " + this.CurrentRecording.Packets.Count); p.AddLength(); if (Client.TibiaVersion >= 770) { p.XteaEncrypt(this.XteaKey, p.GetPosition); p.AddLength(); } p.Send(this.TcpClientLocal); break; case "goto": TimeSpan ts; if (!TimeSpan.TryParse(msgSplit[1], out ts)) { break; } this.FastForward(ts); break; case "pause": this.PlaybackSpeed = 0; break; case "resume": this.PlaybackSpeed = 1; break; } break; } break; } } if (TcpClientLocal != null) { TcpClientLocal.Close(); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message + "\n" + ex.StackTrace); if (TcpClientLocal != null) { TcpClientLocal.Close(); } } }
private void PlaybackSend() { try { Recording.Packet p; this.CurrentPacket = 0; this.DoFastForward = false; uint timeOld = 0, timeNew = 0; bool hasShownInfo = false; this.CurrentRecording.TimePassed = 0; if (this.CurrentRecording.MouseRecording != null) { while (this.threadPlaybackSendMouse != null && this.threadPlaybackSendMouse.IsAlive) { this.threadPlaybackSendMouse.Abort(); Thread.Sleep(100); } this.threadPlaybackSendMouse = new Thread(new ThreadStart(this.PlaybackSendMouse)); threadPlaybackSendMouse.Start(); } try { while (this.CurrentPacket < this.CurrentRecording.Packets.Count) { if (!this.TcpClientLocal.Connected) { return; } if (this.DoFastForward) { if (TimeSpan.FromMilliseconds(this.CurrentRecording.TimePassed) > this.FastForwardTo) { this.CurrentPacket = 0; this.CurrentRecording.TimePassed = 0; } while (this.CurrentPacket < this.CurrentRecording.Packets.Count && this.CurrentRecording.TimePassed < this.FastForwardTo.TotalMilliseconds) { p = this.CurrentRecording.Packets[this.CurrentPacket].Clone(); this.CurrentRecording.TimePassed = p.Time; //if (this.CurrentRecording.Recorder == Enums.Recorder.TibianicTools) p.GetPosition += 4; //else if (this.CurrentRecording.Recorder == Enums.Recorder.TibiaMovie) p.GetPosition += 2; if (Client.TibiaVersion >= 770) { p = p.XteaEncrypt(this.XteaKey, 0); } p.Send(this.TcpClientLocal); this.CurrentPacket++; } this.DoFastForward = false; hasShownInfo = false; } else if (this.PlaybackSpeed <= 0) { Thread.Sleep(200); continue; } if (/*Client.TibiaVersion == 740 && */ !hasShownInfo && this.CurrentPacket > 3 && Client.Player.Connected) { Thread.Sleep(100); Objects.Packet packet = new Objects.Packet(); packet.AddByte(0xb4); // text message packet.AddByte(16); // orange color packet.AddString("Welcome to a Tibianic Tools recording!\nKeyboard hotkeys:\nArrow keys - change playback speed\nBackspace - rewind 1 minute"); packet.AddByte(0xb4); packet.AddByte(16); packet.AddString("Text commands:\ninfo - show recording information\ngoto hh:mm:ss - rewinds/fast forwards to given time\npause - pauses playback\nresume - resumes playback"); packet.AddLength(); if (Client.TibiaVersion >= 770) { packet.XteaEncrypt(this.XteaKey, packet.GetPosition); packet.AddLength(); } packet.Send(this.TcpClientLocal); hasShownInfo = true; Thread.Sleep(20); } p = this.CurrentRecording.Packets[this.CurrentPacket].Clone(); this.CurrentRecording.TimePassed = p.Time; timeNew = this.CurrentRecording.TimePassed; int sleep = (int)((timeNew - timeOld) / this.PlaybackSpeed); //if (this.CurrentRecording.Recorder == Enums.Recorder.TibianicTools) p.GetPosition += 4; // length, not needed //else if (this.CurrentRecording.Recorder == Enums.Recorder.TibiaMovie) p.GetPosition += 2; // -||- // try-catch because Thread.Interrupt() will throw an exception try { if (sleep > 0) { Thread.Sleep(sleep); } } catch { } if (!this.TcpClientLocal.Connected) { return; } if (Client.TibiaVersion >= 770) { p = p.XteaEncrypt(this.XteaKey, 0); } p.Send(this.TcpClientLocal); if (this.CurrentRecording.MouseRecording != null) { MouseRecording mouseRec = this.CurrentRecording.MouseRecording; //int currentTime = mouseRec.Seek(this.CurrentRecording.TimePassed); int mouseTime = mouseRec.CurrentIndex * mouseRec.Interval; int timeMarginMax = mouseTime + 200, timeMarginMin = mouseTime - 200; if (timeNew >= timeMarginMax || timeNew <= timeMarginMin) { this.CurrentRecording.MouseRecording.CurrentIndex = this.CurrentRecording.MouseRecording.Seek(timeNew); } } timeOld = timeNew; this.CurrentPacket++; } } catch { } Thread.Sleep(3000); this.PlaybackSpeed = 1; WinApi.SetWindowText(Client.Tibia.MainWindowHandle, "Tibia"); if (TcpClientLocal != null) { TcpClientLocal.Close(); } if (this.DoKillAfterPlayback && !Client.Tibia.HasExited) { Client.Tibia.Kill(); } else { this.AutoPlayback = false; } } catch (Exception ex) { /*System.Windows.Forms.MessageBox.Show(ex.Message + "\n" + ex.StackTrace);*/ } }