using System; using System.Text; using System.Windows.Forms; namespace MapleShark { public sealed class FiestaPacket: ListViewItem { // Fields public Definition Definition; public byte Header { get; } public byte Type { get; } // Methods // internal FiestaPacket(DateTime pTimestamp, bool pOutbound, ushort pOpcode, string pName, byte[] pBuffer, DateTime pStreamCreated) // : this(pTimestamp, pOutbound, Convert.ToByte(pOpcode >> 10), Convert.ToByte(pOpcode & 1023), pName, pBuffer, pStreamCreated) {} internal FiestaPacket(DateTime pTimestamp, bool pOutbound, ushort pOpcode, string pName, byte[] pBuffer, DateTime pStreamCreated) : base(new[] { ((pTimestamp - pStreamCreated).Ticks / 10000).ToString(), pOutbound ? "Outbound" : "Inbound", pBuffer.Length.ToString(), $"{pOpcode:X}", pName }) { Timestamp = pTimestamp; Outbound = pOutbound; Opcode = pOpcode; //Opcode = Convert.ToUInt16((pHeader << 10) + (pType & 1023)); var preHeader = pOpcode >> 10; var preType = pOpcode & 1023; Header = Convert.ToByte(preHeader); Type = Convert.ToByte(preType); InnerBuffer = pBuffer; Definition = Config.Instance.Definitions.Find(d => d.Outbound == Outbound && d.Opcode == Opcode); } public byte[] Dump() { var dst = new byte[InnerBuffer.Length + 12]; var length = (ushort)InnerBuffer.Length; if( Outbound ) { length = (ushort)(length | 0x8000); } var ticks = Timestamp.Ticks; dst[0] = (byte)ticks; dst[1] = (byte)(ticks >> 8); dst[2] = (byte)(ticks >> 0x10); dst[3] = (byte)(ticks >> 0x18); dst[4] = (byte)(ticks >> 0x20); dst[5] = (byte)(ticks >> 0x28); dst[6] = (byte)(ticks >> 0x30); dst[7] = (byte)(ticks >> 0x38); dst[8] = (byte)length; dst[9] = (byte)(length >> 8); dst[10] = (byte)Opcode; dst[11] = (byte)(Opcode >> 8); Buffer.BlockCopy(InnerBuffer, 0, dst, 12, InnerBuffer.Length); return dst; } public bool ReadByte(out byte pValue) { pValue = 0; if( Cursor + 1 > InnerBuffer.Length ) { return false; } pValue = InnerBuffer[Cursor++]; return true; } public bool ReadBytes(byte[] pBytes) { return ReadBytes(pBytes, 0, pBytes.Length); } public bool ReadBytes(byte[] pBytes, int pStart, int pLength) { if( Cursor + pLength > InnerBuffer.Length ) { return false; } Buffer.BlockCopy(InnerBuffer, Cursor, pBytes, pStart, pLength); Cursor += pLength; return true; } public bool ReadDouble(out double pValue) { pValue = 0.0; if( Cursor + 8 > InnerBuffer.Length ) { return false; } pValue = BitConverter.ToDouble(InnerBuffer, Cursor); Cursor += 8; return true; } public bool ReadFloat(out float pValue) { pValue = 0f; if( Cursor + 4 > InnerBuffer.Length ) { return false; } pValue = BitConverter.ToSingle(InnerBuffer, Cursor); Cursor += 4; return true; } public bool ReadInt(out int pValue) { pValue = 0; if( Cursor + 4 > InnerBuffer.Length ) { return false; } pValue = InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8) | (InnerBuffer[Cursor++] << 0x10) | (InnerBuffer[Cursor++] << 0x18); return true; } public bool ReadLong(out long pValue) { pValue = 0L; if( Cursor + 8 > InnerBuffer.Length ) { return false; } pValue = InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8) | (InnerBuffer[Cursor++] << 0x10) | (InnerBuffer[Cursor++] << 0x18) | InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8) | (InnerBuffer[Cursor++] << 0x10) | (InnerBuffer[Cursor++] << 0x18); return true; } public bool ReadPaddedString(out string pValue, int pLength) { pValue = ""; if( Cursor + pLength > InnerBuffer.Length ) { return false; } var count = 0; while( count < pLength && InnerBuffer[Cursor + count] != 0 ) { count++; } if( count > 0 ) { pValue = Encoding.ASCII.GetString(InnerBuffer, Cursor, count); } Cursor += pLength; return true; } public bool ReadSByte(out sbyte pValue) { pValue = 0; if( Cursor + 1 > InnerBuffer.Length ) { return false; } pValue = (sbyte)InnerBuffer[Cursor++]; return true; } public bool ReadShort(out short pValue) { pValue = 0; if( Cursor + 2 > InnerBuffer.Length ) { return false; } pValue = (short)(InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8)); return true; } public bool ReadUInt(out uint pValue) { pValue = 0; if( Cursor + 4 > InnerBuffer.Length ) { return false; } pValue = (uint)(InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8) | (InnerBuffer[Cursor++] << 0x10) | (InnerBuffer[Cursor++] << 0x18)); return true; } public bool ReadULong(out ulong pValue) { pValue = 0L; if( Cursor + 8 > InnerBuffer.Length ) { return false; } pValue = (ulong)(InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8) | (InnerBuffer[Cursor++] << 0x10) | (InnerBuffer[Cursor++] << 0x18) | InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8) | (InnerBuffer[Cursor++] << 0x10) | (InnerBuffer[Cursor++] << 0x18)); return true; } public bool ReadUShort(out ushort pValue) { pValue = 0; if( Cursor + 2 > InnerBuffer.Length ) { return false; } pValue = (ushort)(InnerBuffer[Cursor++] | (InnerBuffer[Cursor++] << 8)); return true; } public void Rewind() { Cursor = 0; } // Properties public int Cursor { get; private set; } public byte[] InnerBuffer { get; } public int Length => InnerBuffer.Length; public string DefinitionName { set => SubItems[4].Text = value; } public ushort Opcode { get; } public bool Outbound { get; } public int Remaining => InnerBuffer.Length - Cursor; public DateTime Timestamp { get; } public void ReverseCursor(int pLength) { Cursor -= pLength; } } }