Exemple #1
0
        public static void ParseUpdatePacket(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe)
        {
            string database_log = "data.txt";
            StreamWriter data2 = new StreamWriter(database_log, true);
            data2.AutoFlush = true;

            sb.AppendLine("Packet offset " + (gr.BaseStream.Position - 2).ToString("X2"));

            //sb.AppendLine("Packet number: " + packet);

            uint count = gr2.ReadUInt32();
            sb.AppendLine("Object count: " + count);

            uint unk = gr2.ReadByte();
            sb.AppendLine("HasTransport: " + unk);

            for (uint i = 1; i < count + 1; i++)
            {
                sb.AppendLine("Update block for object " + i + ":");
                sb.AppendLine("Block offset " + gr.BaseStream.Position.ToString("X2"));

                if (!ParseBlock(gr2, sb, swe, data2))
                    break;
            }

            if (gr2.BaseStream.Position == gr2.BaseStream.Length)
                sb.AppendLine("packet parse: OK...");
            else
                sb.AppendLine("packet parse: ERROR!");

            data2.Flush();
            data2.Close();
        }
        public static bool ParseAttackerStateUpdateOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_ATTACKERSTATEUPDATE (0x01B1)");

            StreamWriter sw = new StreamWriter("attacker_state.log", true, Encoding.ASCII);

            HitInfo hi = (HitInfo)gr2.ReadUInt32();
            ulong attacker = gr2.ReadPackedGuid();
            ulong target = gr2.ReadPackedGuid();

            uint damage = gr2.ReadUInt32();

            sw.WriteLine("HitInfo {0}", hi);
            sw.WriteLine("attacker {0}", attacker.ToString("X16"));
            sw.WriteLine("target {0}", target.ToString("X16"));
            sw.WriteLine("damage {0}", damage);

            byte count = gr2.ReadByte();
            sw.WriteLine("count {0}", count);

            for (byte i = 0; i < count; i++)
            {
                ITEM_DAMAGE_TYPE damagetype = (ITEM_DAMAGE_TYPE)gr2.ReadUInt32();
                float damage2 = gr2.ReadSingle();
                uint damage3 = gr2.ReadUInt32();
                uint adsorb = gr2.ReadUInt32();
                uint resist = gr2.ReadUInt32();

                sw.WriteLine("damagetype {0}", damagetype);
                sw.WriteLine("damage2 {0}", damage2);
                sw.WriteLine("damage3 {0}", damage3);
                sw.WriteLine("adsorb {0}", adsorb);
                sw.WriteLine("resist {0}", resist);
            }

            VictimState targetstate = (VictimState)gr2.ReadUInt32();
            uint unk1 = gr2.ReadUInt32();
            uint unk2 = gr2.ReadUInt32();
            uint blocked = gr2.ReadUInt32();

            sw.WriteLine("targetstate {0}", targetstate);
            sw.WriteLine("unk1 {0}", unk1);
            sw.WriteLine("unk2 {0}", unk2);
            sw.WriteLine("blocked {0}", blocked);
            sw.WriteLine();

            sw.Flush();
            sw.Close();

            if (gr2.BaseStream.Position == gr2.BaseStream.Length)
                sb.AppendLine("parsed: ok...");
            else
                sb.AppendLine("parsed: error...");

            return true;
        }
Exemple #3
0
        private static void HexLike(GenericReader gr, StreamWriter hex, uint id, uint sess_id, string time, byte direction, OpCodes opcode)
        {
            int length = (int)(gr.Remaining);

            string dir = "";

            if (direction == 0)
                dir = "C->S";
            else
                dir = "S->C";

            hex.WriteLine("Packet {0}, id {1}, {2} ({3}), len {4}", dir, id, opcode, (ushort)opcode, length);
            //hex.WriteLine("Session {0}, time {1}", sess_id, time);

            int byteIndex = 0;

            int full_lines = length >> 4;
            int rest = length & 0x0F;

            if ((full_lines == 0) && (rest == 0)) // empty packet (no data provided)
            {
                hex.WriteLine("0000: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ................");
            }
            else
            {
                for (int i = 0; i < full_lines; ++i, byteIndex += 0x10)
                {
                    StringBuilder bytes = new StringBuilder();
                    StringBuilder chars = new StringBuilder();

                    for (int j = 0; j < 0x10; ++j)
                    {
                        int c = gr.ReadByte();

                        bytes.Append(c.ToString("X2"));

                        bytes.Append(' ');

                        if (c >= 0x20 && c < 0x80)
                            chars.Append((char)c);
                        else
                            chars.Append('.');
                    }

                    hex.WriteLine(byteIndex.ToString("X4") + ": " + bytes.ToString() + "| " + chars.ToString());
                }

                if (rest != 0)
                {
                    StringBuilder bytes = new StringBuilder();
                    StringBuilder chars = new StringBuilder(rest);

                    for (int j = 0; j < 0x10; ++j)
                    {
                        if (j < rest)
                        {
                            int c = gr.ReadByte();

                            bytes.Append(c.ToString("X2"));

                            bytes.Append(' ');

                            if (c >= 0x20 && c < 0x80)
                                chars.Append((char)c);
                            else
                                chars.Append('.');
                        }
                        else
                            bytes.Append("-- ");
                    }
                    hex.WriteLine(byteIndex.ToString("X4") + ": " + bytes.ToString() + "| " + chars.ToString());
                }
            }

            hex.WriteLine();
        }
Exemple #4
0
        /// <summary>
        /// Packet header parser.
        /// </summary>
        /// <param name="gr">Main stream reader.</param>
        /// <param name="sw">Data stream writer.</param>
        /// <param name="swe">Error logger writer.</param>
        /// <param name="data">Data logger writer.</param>
        /// <param name="hex">HEX logger writer.</param>
        /// <returns>Successful</returns>
        private static bool ParseHeader(GenericReader gr, StreamWriter sw, StreamWriter swe, StreamWriter data, StreamWriter hex)
        {
            StringBuilder sb = new StringBuilder();

            int datasize = gr.ReadInt32();

            //sb.AppendLine("Packet offset " + (gr.BaseStream.Position - 4).ToString("X2"));

            //sb.AppendLine("Packet number: " + packet);

            //sb.AppendLine("Data size " + datasize);

            byte[] temp = gr.ReadBytes(datasize);
            MemoryStream ms = new MemoryStream(temp);
            GenericReader gr2 = new GenericReader(ms);

            uint id = 0;
            uint sess_id = 0;
            string time = "";
            byte direction = 0; // 0-CMSG, 1-SMSG
            OpCodes opcode = OpCodes.MSG_NULL_ACTION;

            id = gr2.ReadUInt32();
            sess_id = gr2.ReadUInt32();
            time = gr2.ReadStringNull();
            direction = gr2.ReadByte();
            opcode = (OpCodes)gr2.ReadUInt16();

            long cur_pos = gr2.BaseStream.Position;

            HexLike(gr2, hex, id, sess_id, time, direction, opcode);

            gr2.BaseStream.Position = cur_pos;

            switch (opcode)
            {
                /*case OpCodes.SMSG_MONSTER_MOVE:
                    OpcodeParser.ParseMonsterMoveOpcode(gr, gr2, sb, swe, direction);
                    break;*/
                /*case OpCodes.SMSG_INITIAL_SPELLS:
                    OpcodeParser.ParseInitialSpellsOpcode(gr, gr2, sb, swe, direction);
                    break;
                case OpCodes.SMSG_AUCTION_LIST_RESULT:
                    OpcodeParser.ParseAuctionListResultOpcode(gr, gr2, sb, swe, direction);
                    break;*/
                /*case OpCodes.SMSG_PARTY_MEMBER_STATS:
                case OpCodes.SMSG_PARTY_MEMBER_STATS_FULL:
                    OpcodeParser.ParsePartyMemberStatsOpcode(gr, gr2, sb, swe, direction);
                    break;*/
                case OpCodes.SMSG_UPDATE_OBJECT:
                case OpCodes.SMSG_COMPRESSED_UPDATE_OBJECT:
                    if (opcode == OpCodes.SMSG_COMPRESSED_UPDATE_OBJECT)
                    {
                        gr2 = A9.Decompress(gr2);
                        gr2.BaseStream.Position = 0;
                        hex.WriteLine("Decompressed SMSG_COMPRESSED_UPDATE_OBJECT:");
                        HexLike(gr2, hex, id, sess_id, time, direction, OpCodes.SMSG_UPDATE_OBJECT);
                        gr2.BaseStream.Position = 0;
                    }
                    A9.ParseUpdatePacket(gr, gr2, sb, swe);
                    break;
                /*case OpCodes.SMSG_SPELLNONMELEEDAMAGELOG:
                    OpcodeParser.ParseSpellNonMeleeDamageLogOpcode(gr, gr2, sb, swe, direction);
                    break;
                case OpCodes.SMSG_SPELLLOGEXECUTE:
                    OpcodeParser.ParseSpellLogExecuteOpcode(gr, gr2, sb, swe, direction);
                    break;*/
                /*case OpCodes.SMSG_LOGIN_SETTIMESPEED:
                    OpcodeParser.ParseLoginSetTimeSpeedOpcode(gr, gr2, sb, swe, direction);
                    break;
                case OpCodes.SMSG_TRAINER_LIST:
                    OpcodeParser.ParseTrainerListOpcode(gr, gr2, sb, swe, direction);
                    break;
                case OpCodes.SMSG_ATTACKERSTATEUPDATE:
                    OpcodeParser.ParseAttackerStateUpdateOpcode(gr, gr2, sb, swe, direction);
                    break;
                case OpCodes.MSG_CORPSE_QUERY:
                    OpcodeParser.ParseCorpseQueryOpcode(gr, gr2, sb, swe, direction);
                    break;
                case OpCodes.SMSG_LOGIN_VERIFY_WORLD:
                    OpcodeParser.ParseLoginVerifyWorldOpcode(gr, gr2, sb, swe, direction);
                    break;
                default:    // unhandled opcode
                    return false;*/
            }

            if (sb.ToString().Length != 0)
                sw.WriteLine(sb.ToString());

            ms.Close();
            gr2.Close();

            return true;
        }
Exemple #5
0
        private static bool ParseBlock(GenericReader gr, StringBuilder sb, StreamWriter swe, StreamWriter data)
        {
            ulong guid = 0;

            UpdateTypes updatetype = (UpdateTypes)gr.ReadByte();
            sb.AppendLine("Updatetype: " + updatetype);

            // check if updatetype is valid
            if (updatetype < UpdateTypes.UPDATETYPE_VALUES || updatetype > UpdateTypes.UPDATETYPE_NEAR_OBJECTS)
            {
                long pos = gr.BaseStream.Position;
                swe.WriteLine("wrong updatetype at position {0}", pos.ToString("X16"));

                // we there only if we read packet wrong way
                swe.WriteLine("Updatetype {0} is not supported", updatetype);
                return false;
            }

            switch (updatetype)
            {
                case UpdateTypes.UPDATETYPE_VALUES:
                    guid = gr.ReadPackedGuid();
                    sb.AppendLine("Object guid: " + guid.ToString("X16"));

                    if (guid == 0)
                    {
                        long pos = gr.BaseStream.Position;
                        swe.WriteLine("wrong guid at position {0}", pos.ToString("X2"));

                        // we there only if we read packet wrong way
                        swe.WriteLine("Updatetype {0} can't be with NULL guid", updatetype);
                        return false;
                    }

                    ObjectTypes objecttype = ObjectTypes.TYPEID_OBJECT; // 0
                    if (Binparser.m_objects.ContainsKey(guid))
                        objecttype = Binparser.m_objects[guid];
                    else    // try old method...
                    {
                        // object type auto detection:
                        // F00C0000, F02B0000 - gameobjects
                        // F00CXXXX, F02BXXXX - units (XXXX == 0000 for pets etc...)
                        // F02B00000000XXXX - corpses
                        // F02B00000000XXXX - dynamicobjects
                        if (guid.ToString("X16").Substring(0, 8).Equals("40000000"))
                            objecttype = ObjectTypes.TYPEID_ITEM;
                        else if (guid.ToString("X16").Substring(0, 8).Equals("00000000"))
                            objecttype = ObjectTypes.TYPEID_PLAYER;
                        else
                            objecttype = ObjectTypes.TYPEID_UNIT; // also can be go, do, corpse

                        swe.WriteLine("problem with objecttypeid detection for UPDATETYPE_VALUES");
                    }

                    sb.AppendLine("objectTypeId " + objecttype);

                    if (!ParseValuesUpdateBlock(gr, sb, swe, data, objecttype, updatetype, null))
                        return false;

                    return true;
                case UpdateTypes.UPDATETYPE_MOVEMENT:
                    guid = gr.ReadPackedGuid();
                    sb.AppendLine("Object guid: " + guid.ToString("X16"));

                    if (!ParseMovementUpdateBlock(gr, sb, swe, data, ObjectTypes.TYPEID_UNIT, null))
                        return false;

                    return true;
                case UpdateTypes.UPDATETYPE_CREATE_OBJECT:
                case UpdateTypes.UPDATETYPE_CREATE_OBJECT2:
                    guid = gr.ReadPackedGuid();
                    sb.AppendLine("Object guid: " + guid.ToString("X16"));

                    ObjectTypes objectTypeId = (ObjectTypes)gr.ReadByte();
                    sb.AppendLine("objectTypeId " + objectTypeId);

                    // check object existance and remove it if needed...
                    //if (Binparser.m_objects.ContainsKey(guid))
                    //    Binparser.m_objects.Remove(guid);

                    // now we can add this object to Dictionary to get correct object type later...
                    //Binparser.m_objects.Add(guid, objectTypeId);

                    WoWObject obj = new WoWObject(0, objectTypeId);

                    // add new object only if we not have it already
                    if (!Binparser.m_objects.ContainsKey(guid))
                    {
                        obj.IsNew = true;
                        Binparser.m_objects.Add(guid, objectTypeId);
                    }

                    switch (objectTypeId)
                    {
                        case ObjectTypes.TYPEID_OBJECT:
                        case ObjectTypes.TYPEID_AIGROUP:
                        case ObjectTypes.TYPEID_AREATRIGGER:
                            swe.WriteLine("Unhandled object type {0}", objectTypeId);
                            return false;
                        case ObjectTypes.TYPEID_ITEM:
                        case ObjectTypes.TYPEID_CONTAINER:
                        case ObjectTypes.TYPEID_UNIT:
                        case ObjectTypes.TYPEID_PLAYER:
                        case ObjectTypes.TYPEID_GAMEOBJECT:
                        case ObjectTypes.TYPEID_DYNAMICOBJECT:
                        case ObjectTypes.TYPEID_CORPSE:
                            if (!ParseMovementUpdateBlock(gr, sb, swe, data, objectTypeId, obj))
                                return false;
                            if (!ParseValuesUpdateBlock(gr, sb, swe, data, objectTypeId, updatetype, obj))
                                return false;
                            return true;
                        default:
                            swe.WriteLine("Unknown object type {0}", objectTypeId);
                            return false;
                    }
                case UpdateTypes.UPDATETYPE_OUT_OF_RANGE_OBJECTS:
                case UpdateTypes.UPDATETYPE_NEAR_OBJECTS:
                    uint objects_count = gr.ReadUInt32();

                    if (objects_count > 1000) // we read packet wrong way
                    {
                        long pos = gr.BaseStream.Position;
                        swe.WriteLine("error position {0}", pos.ToString("X2"));

                        swe.WriteLine("Too many {0} objects", updatetype);
                        return false;
                    }

                    sb.AppendLine("guids_count " + objects_count);

                    for (uint i = 0; i < objects_count; i++)
                        sb.AppendLine("Guid" + i + ": " + gr.ReadPackedGuid().ToString("X16"));
                    return true;
                default:
                    swe.WriteLine("Unknown updatetype {0}", updatetype);
                    return false;
            }
        }
Exemple #6
0
        private static bool ParseMovementUpdateBlock(GenericReader gr, StringBuilder sb, StreamWriter swe, StreamWriter data, ObjectTypes objectTypeId, WoWObject obj)
        {
            Coords4 coords;
            coords.X = 0;
            coords.Y = 0;
            coords.Z = 0;
            coords.O = 0;

            sb.AppendLine("=== movement_update_block_start ===");
            MovementFlags mf = MovementFlags.MOVEMENTFLAG_NONE;    // movement flags

            UpdateFlags flags = (UpdateFlags)gr.ReadByte();
            sb.AppendLine("Update Flags: " + flags.ToString("X") + " : " + flags);

            if ((UpdateFlags.UPDATEFLAG_LIVING & flags) != 0) // 0x20
            {
                mf = (MovementFlags)gr.ReadUInt32();
                sb.AppendLine("Movement Flags: " + mf.ToString("X") + " : " + mf);

                byte unk = gr.ReadByte();
                sb.AppendLine("Unknown Byte: " + unk.ToString("X2"));

                uint time = gr.ReadUInt32();
                sb.AppendLine("Time: " + time.ToString("X8"));
            }

            if ((UpdateFlags.UPDATEFLAG_HASPOSITION & flags) != 0) // 0x40
            {
                coords = gr.ReadCoords4();
                sb.AppendLine("Coords: " + coords.GetCoordsAsString());

                if (objectTypeId == ObjectTypes.TYPEID_UNIT || objectTypeId == ObjectTypes.TYPEID_GAMEOBJECT)
                {
                    if (obj != null)
                        obj.SetPosition(coords.X, coords.Y, coords.Z, coords.O);
                }
            }

            if ((flags & UpdateFlags.UPDATEFLAG_LIVING) != 0)   // 0x20
            {
                /*if (objectTypeId == ObjectTypes.TYPEID_UNIT || objectTypeId == ObjectTypes.TYPEID_GAMEOBJECT)
                {
                    data.WriteLine();
                    data.WriteLine(objectTypeId + ": " + coords.GetCoordsAsString());
                }*/

                if ((mf & MovementFlags.MOVEMENTFLAG_ONTRANSPORT) != 0) // transport
                {
                    ulong t_guid = gr.ReadUInt64();
                    sb.Append("Transport GUID: " + t_guid.ToString("X16") + ", ");

                    Coords4 transport = gr.ReadCoords4();
                    sb.AppendLine("Transport Coords: " + transport.GetCoordsAsString());

                    uint unk2 = gr.ReadUInt32(); // unk, probably timestamp
                    sb.AppendLine("Transport Unk: " + unk2.ToString("X8"));
                }

                if ((mf & (MovementFlags.MOVEMENTFLAG_SWIMMING | MovementFlags.MOVEMENTFLAG_UNK5)) != 0)
                {
                    float unkf1 = gr.ReadSingle();
                    sb.AppendLine("MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_UNK5): " + unkf1);
                }

                uint unk1 = gr.ReadUInt32();
                sb.AppendLine("Unk1: " + unk1.ToString("X8"));

                if ((mf & MovementFlags.MOVEMENTFLAG_JUMPING) != 0)
                {
                    // looks like orientation/coords/speed
                    float unk3 = gr.ReadSingle();
                    sb.AppendLine("unk3: " + unk3);
                    float unk4 = gr.ReadSingle();
                    sb.AppendLine("unk4: " + unk4);
                    float unk5 = gr.ReadSingle();
                    sb.AppendLine("unk5: " + unk5);
                    float unk6 = gr.ReadSingle();
                    sb.AppendLine("unk6: " + unk6);
                }

                if ((mf & MovementFlags.MOVEMENTFLAG_SPLINE) != 0)
                {
                    float unkf2 = gr.ReadSingle();
                    sb.AppendLine("MovementFlags & MOVEMENTFLAG_SPLINE: " + unkf2);
                }

                float ws = gr.ReadSingle();
                sb.AppendLine("Walk speed: " + ws);
                float rs = gr.ReadSingle();
                sb.AppendLine("Run speed: " + rs);
                float sbs = gr.ReadSingle();
                sb.AppendLine("Swimback speed: " + sbs);
                float ss = gr.ReadSingle();
                sb.AppendLine("Swim speed: " + ss);
                float wbs = gr.ReadSingle();
                sb.AppendLine("Walkback speed: " + wbs);
                float fs = gr.ReadSingle();
                sb.AppendLine("Fly speed: " + fs);
                float fbs = gr.ReadSingle();
                sb.AppendLine("Flyback speed: " + fbs);
                float ts = gr.ReadSingle();
                sb.AppendLine("Turn speed: " + ts); // pi = 3.14

                if ((mf & MovementFlags.MOVEMENTFLAG_SPLINE2) != 0)
                {
                    uint flags3 = gr.ReadUInt32();
                    sb.AppendLine("SplineFlags " + flags3.ToString("X8"));

                    if ((flags3 & 0x10000) != 0)
                    {
                        Coords3 c = gr.ReadCoords3();
                        sb.AppendLine("SplineFlags & 0x10000: " + c.GetCoords());
                    }
                    if ((flags3 & 0x20000) != 0)
                    {
                        ulong g3 = gr.ReadUInt64();
                        sb.AppendLine("flags3_guid: " + g3.ToString("X16")); // ????
                    }
                    if ((flags3 & 0x40000) != 0)
                    {
                        uint f3_3 = gr.ReadUInt32();
                        sb.AppendLine("flags3_unk_value3: " + f3_3.ToString("X8"));
                    }

                    uint t1 = gr.ReadUInt32();
                    sb.AppendLine("curr tick: " + t1.ToString("X8"));

                    uint t2 = gr.ReadUInt32();
                    sb.AppendLine("last tick: " + t2.ToString("X8"));

                    uint t3 = gr.ReadUInt32();
                    sb.AppendLine("tick count " + t3.ToString("X8"));

                    uint coords_count = gr.ReadUInt32();
                    sb.AppendLine("coords_count: " + coords_count.ToString("X8"));

                    for (uint i = 0; i < coords_count; i++)
                    {
                        Coords3 v = gr.ReadCoords3();
                        sb.AppendLine("coord" + i + ": " + v.GetCoords());
                    }

                    Coords3 end = gr.ReadCoords3();
                    sb.AppendLine("end: " + end.GetCoords());
                }
            }

            if ((flags & UpdateFlags.UPDATEFLAG_LOWGUID) != 0)   // 0x08
            {
                uint temp = gr.ReadUInt32(); // timestamp or something like it
                sb.AppendLine("UpdateFlags & 0x08 (lowguid): " + temp.ToString("X8"));
            }

            if ((UpdateFlags.UPDATEFLAG_HIGHGUID & flags) != 0) // 0x10
            {
                uint guid_high = gr.ReadUInt32(); // timestamp or something like it
                sb.AppendLine("UpdateFlags & 0x10 (highguid): " + guid_high.ToString("X8"));
            }

            if ((UpdateFlags.UPDATEFLAG_FULLGUID & flags) != 0) // 0x04
            {
                ulong guid2 = gr.ReadPackedGuid(); // guid, but what guid?
                sb.AppendLine("UpdateFlags & 0x04 guid: " + guid2.ToString("X16"));
            }

            if ((UpdateFlags.UPDATEFLAG_TRANSPORT & flags) != 0) // 0x02
            {
                uint time = gr.ReadUInt32(); // time
                sb.AppendLine("UpdateFlags & 0x02 t_time: " + time.ToString("X8"));
            }

            if ((UpdateFlags.UPDATEFLAG_SELFTARGET & flags) != 0) // 0x01
            {
                sb.AppendLine("updating self!");
            }

            sb.AppendLine("=== movement_update_block_end ===");
            return true;
        }
Exemple #7
0
        private static bool ParseValuesUpdateBlock(GenericReader gr, StringBuilder sb, StreamWriter swe, StreamWriter data, ObjectTypes objectTypeId, UpdateTypes updatetype, WoWObject obj)
        {
            sb.AppendLine("=== values_update_block_start ===");

            byte blocks_count = gr.ReadByte(); // count of update blocks (4 bytes for each update block)
            sb.AppendLine("Bit mask blocks count: " + blocks_count);

            int[] updatemask = new int[blocks_count]; // create array of update blocks
            for (int j = 0; j < blocks_count; j++)
                updatemask[j] = gr.ReadInt32(); // populate array of update blocks with data

            Mask = new BitArray(updatemask);

            int reallength = Mask.Count; // bitmask size (bits)

            int bitmask_max_size = 0;
            uint values_end = 0;

            switch (objectTypeId)
            {
                case ObjectTypes.TYPEID_ITEM:
                    bitmask_max_size = 64;
                    values_end = UpdateFieldsLoader.ITEM_END;
                    break;
                case ObjectTypes.TYPEID_CONTAINER:
                    bitmask_max_size = 160;
                    values_end = UpdateFieldsLoader.CONTAINER_END;
                    break;
                case ObjectTypes.TYPEID_UNIT:
                    bitmask_max_size = 256;
                    values_end = UpdateFieldsLoader.UNIT_END;
                    break;
                case ObjectTypes.TYPEID_PLAYER:
                    bitmask_max_size = 1536; // 2.3.2 - 1472
                    values_end = UpdateFieldsLoader.PLAYER_END;
                    break;
                case ObjectTypes.TYPEID_GAMEOBJECT:
                    bitmask_max_size = 32;
                    values_end = UpdateFieldsLoader.GO_END;
                    break;
                case ObjectTypes.TYPEID_DYNAMICOBJECT:
                    bitmask_max_size = 32;
                    values_end = UpdateFieldsLoader.DO_END;
                    break;
                case ObjectTypes.TYPEID_CORPSE:
                    bitmask_max_size = 64;
                    values_end = UpdateFieldsLoader.CORPSE_END;
                    break;
            }

            if (reallength > bitmask_max_size)
            {
                long pos = gr.BaseStream.Position;
                swe.WriteLine("error position {0}", pos.ToString("X2"));

                swe.WriteLine("error while parsing {0} values update block, count {1}", objectTypeId, reallength);
                return false;
            }

            for (int index = 0; index < reallength; index++)
            {
                if (index > values_end)
                    break;

                if (Mask[index])
                {
                    UpdateField uf = new UpdateField();
                    switch (objectTypeId)
                    {
                        case ObjectTypes.TYPEID_ITEM:
                        case ObjectTypes.TYPEID_CONTAINER:
                            uf = UpdateFieldsLoader.item_uf[index];
                            break;
                        case ObjectTypes.TYPEID_UNIT:
                        case ObjectTypes.TYPEID_PLAYER:
                            uf = UpdateFieldsLoader.unit_uf[index];
                            break;
                        case ObjectTypes.TYPEID_GAMEOBJECT:
                            uf = UpdateFieldsLoader.go_uf[index];
                            break;
                        case ObjectTypes.TYPEID_DYNAMICOBJECT:
                            uf = UpdateFieldsLoader.do_uf[index];
                            break;
                        case ObjectTypes.TYPEID_CORPSE:
                            uf = UpdateFieldsLoader.corpse_uf[index];
                            break;
                    }
                    ReadAndDumpField(uf, sb, gr, updatetype, data, obj);
                }
            }

            if ((objectTypeId == ObjectTypes.TYPEID_GAMEOBJECT || objectTypeId == ObjectTypes.TYPEID_UNIT) && (updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT || updatetype == UpdateTypes.UPDATETYPE_CREATE_OBJECT2) && obj.IsNew)
                obj.Save();

            sb.AppendLine("=== values_update_block_end ===");
            return true;
        }
        public static bool ParseTrainerListOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_TRAINER_LIST (0x01B1)");

            StreamWriter sw = new StreamWriter("trainer.log", true, Encoding.ASCII);

            ulong guid = gr2.ReadUInt64();
            TrainerType trainer_type = (TrainerType)gr2.ReadUInt32();
            uint spells_count = gr2.ReadUInt32();

            sw.WriteLine("Trainer {0}, type {1}, spells_count {2}", guid.ToString("X16"), trainer_type, spells_count);

            for (uint i = 0; i < spells_count; i++)
            {
                uint spellid = gr2.ReadUInt32();
                TrainerSpellState state = (TrainerSpellState)gr2.ReadByte();
                uint spellcost = gr2.ReadUInt32();
                uint unk1 = gr2.ReadUInt32();   // isProfession?
                uint unk2 = gr2.ReadUInt32();
                byte reqlevel = gr2.ReadByte();
                uint reqskill = gr2.ReadUInt32();
                uint reqskillvalue = gr2.ReadUInt32();
                uint reqspell = gr2.ReadUInt32();
                uint unk3 = gr2.ReadUInt32();
                uint unk4 = gr2.ReadUInt32();

                sw.WriteLine("Spell {0}, state {1}, cost {2}, unk1 {3}, unk2 {4}, reqlevel {5}, reqskill {6}, reqskillvalue {7}, reqspell {8}, unk3 {9} unk4 {10}", spellid, state, spellcost, unk1, unk2, reqlevel, reqskill, reqskillvalue, reqspell, unk3, unk4);
            }

            string title = gr2.ReadStringNull();
            sw.WriteLine("title {0}", title);

            sw.Flush();
            sw.Close();

            if (gr2.BaseStream.Position == gr2.BaseStream.Length)
                sb.AppendLine("parsed: ok...");
            else
                sb.AppendLine("parsed: error...");

            return true;
        }
        public static bool ParseSpellNonMeleeDamageLogOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            StreamWriter sw = new StreamWriter("SpellNonMeleeDamageLog.log", true, Encoding.ASCII);

            sw.WriteLine("Packet offset {0}", gr.BaseStream.Position.ToString("X2"));
            sw.WriteLine("Opcode SpellNonMeleeDamageLog (0x0250)");

            ulong target = gr2.ReadPackedGuid();
            ulong caster = gr2.ReadPackedGuid();
            sw.WriteLine("target {0}, caster {1}", target, caster);
            uint spellid = gr2.ReadUInt32();
            sw.WriteLine("spell {0}", spellid);
            uint damage = gr2.ReadUInt32();
            sw.WriteLine("damage {0}", damage);
            byte unk1 = gr2.ReadByte();
            sw.WriteLine("unk1 {0}", unk1);
            uint adsorb = gr2.ReadUInt32();
            sw.WriteLine("adsorb {0}", adsorb);
            uint resist = gr2.ReadUInt32();
            sw.WriteLine("resist {0}", resist);
            byte unk2 = gr2.ReadByte();
            sw.WriteLine("unk2 {0}", unk2);
            byte unk3 = gr2.ReadByte();
            sw.WriteLine("unk3 {0}", unk3);
            uint blocked = gr2.ReadUInt32();
            sw.WriteLine("blocked {0}", blocked);
            uint flags = gr2.ReadUInt32();
            sw.WriteLine("flags {0}", flags.ToString("X8"));
            byte unk4 = gr2.ReadByte();
            sw.WriteLine("unk4 {0}", unk4);

            if ((flags & 0x1) != 0)
            {
                float a = gr2.ReadSingle();
                float b = gr2.ReadSingle();
                sw.WriteLine("0x1: a {0}, b {1}", a, b);
            }
            if ((flags & 0x4) != 0)
            {
                float a = gr2.ReadSingle();
                float b = gr2.ReadSingle();
                sw.WriteLine("0x4: a {0}, b {1}", a, b);
            }
            if ((flags & 0x20) != 0)
            {
                float a = gr2.ReadSingle();
                float b = gr2.ReadSingle();
                float c = gr2.ReadSingle();
                float d = gr2.ReadSingle();
                float e = gr2.ReadSingle();
                float f = gr2.ReadSingle();
                sw.WriteLine("0x20: a {0}, b {1}, c {2}, d {3}, e {4}, f {5}", a, b, c, d, e, f);
            }

            if (gr2.BaseStream.Position != gr2.BaseStream.Length)
                sw.WriteLine("F**K!: " + flags.ToString("X8"));

            sw.WriteLine();
            sw.Flush();
            sw.Close();

            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="gr"></param>
        /// <param name="gr2"></param>
        /// <param name="sb"></param>
        /// <param name="swe"></param>
        /// <returns></returns>
        public static bool ParsePartyMemberStatsOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_PARTY_MEMBER_STATS (0x007E)");

            byte MAX_AURAS = 56;

            ulong guid = gr2.ReadPackedGuid();
            sb.AppendLine("GUID " + guid.ToString("X16"));

            GroupUpdateFlags flags = (GroupUpdateFlags)gr2.ReadUInt32();
            sb.AppendLine("Flags " + flags);

            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_ONLINE) != 0)
            {
                GroupMemberOnlineStatus online = (GroupMemberOnlineStatus)gr2.ReadUInt16(); // flag
                sb.AppendLine("Online state " + online);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_CUR_HP) != 0)
            {
                ushort hp = gr2.ReadUInt16();
                sb.AppendLine("Cur. health " + hp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_MAX_HP) != 0)
            {
                ushort maxhp = gr2.ReadUInt16();
                sb.AppendLine("Max health " + maxhp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_POWER_TYPE) != 0)
            {
                Powers power = (Powers)gr2.ReadByte();
                sb.AppendLine("Power type " + power);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_CUR_POWER) != 0)
            {
                ushort curpower = gr2.ReadUInt16();
                sb.AppendLine("Cur. power " + curpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_MAX_POWER) != 0)
            {
                ushort maxpower = gr2.ReadUInt16();
                sb.AppendLine("Max power " + maxpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_LEVEL) != 0)
            {
                ushort level = gr2.ReadUInt16();
                sb.AppendLine("Level " + level);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_ZONE) != 0)
            {
                ushort zone = gr2.ReadUInt16();
                sb.AppendLine("Zone " + zone);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_POSITION) != 0)
            {
                short x = gr2.ReadInt16();
                short y = gr2.ReadInt16();
                sb.AppendLine("Position: " + x + ", " + y);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_AURAS) != 0)
            {
                ulong mask = gr2.ReadUInt64();
                sb.AppendLine("Auras mask " + mask.ToString("X16"));

                BitArray bitArr = new BitArray(BitConverter.GetBytes(mask));

                for (int i = 0; i < bitArr.Length; i++)
                {
                    if (i >= MAX_AURAS) // we can have only 56 auras
                        break;

                    if (bitArr[i])
                    {
                        ushort spellid = gr2.ReadUInt16();
                        sb.AppendLine("Aura " + i.ToString() + ": " + spellid.ToString());
                        byte unk = gr2.ReadByte();
                        sb.AppendLine("Aura unk " + i.ToString() + ": " + unk.ToString());
                    }
                }
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_GUID) != 0)
            {
                ulong petguid = gr2.ReadUInt64();
                sb.AppendLine("Pet guid " + petguid.ToString("X16"));
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_NAME) != 0)
            {
                string name = gr2.ReadStringNull();
                sb.AppendLine("Pet name " + name);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_MODEL_ID) != 0)
            {
                ushort modelid = gr2.ReadUInt16();
                sb.AppendLine("Pet model id " + modelid);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_CUR_HP) != 0)
            {
                ushort pethp = gr2.ReadUInt16();
                sb.AppendLine("Pet cur. HP " + pethp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_MAX_HP) != 0)
            {
                ushort petmaxhp = gr2.ReadUInt16();
                sb.AppendLine("Pet max HP " + petmaxhp);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_POWER_TYPE) != 0)
            {
                Powers power = (Powers)gr2.ReadByte();
                sb.AppendLine("Pet power type " + power);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_CUR_POWER) != 0)
            {
                ushort petpower = gr2.ReadUInt16();
                sb.AppendLine("Pet cur. power " + petpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_MAX_POWER) != 0)
            {
                ushort petmaxpower = gr2.ReadUInt16();
                sb.AppendLine("Pet max power " + petmaxpower);
            }
            if ((flags & GroupUpdateFlags.GROUP_UPDATE_FLAG_PET_AURAS) != 0)
            {
                ulong mask = gr2.ReadUInt64();
                sb.AppendLine("Pet auras mask " + mask.ToString("X16"));

                BitArray bitArr = new BitArray(BitConverter.GetBytes(mask));
                for (int i = 0; i < bitArr.Length; i++)
                {
                    if (i >= MAX_AURAS) // we can have only 56 auras
                        break;

                    if (bitArr[i])
                    {
                        ushort spellid = gr2.ReadUInt16();
                        sb.AppendLine("Pet aura " + i.ToString() + ": " + spellid.ToString());
                        byte unk = gr2.ReadByte();
                        sb.AppendLine("Pet aura unk " + i.ToString() + ": " + unk.ToString());
                    }
                    i++;
                }
            }

            if (gr2.BaseStream.Position == gr2.BaseStream.Length)
                sb.AppendLine("parsed: ok...");
            else
                sb.AppendLine("parsed: error...");

            return true;
        }
        /// <summary>
        /// Monster move opcode parser method.
        /// </summary>
        /// <param name="gr">Main stream reader.</param>
        /// <param name="gr2">Packet stream reader.</param>
        /// <param name="sb">Logger string builder.</param>
        /// <param name="swe">Error logger writer.</param>
        /// <returns>Successful</returns>
        public static bool ParseMonsterMoveOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_MONSTER_MOVE (0x00DD)");

            ulong guid = gr2.ReadPackedGuid();
            sb.AppendLine("GUID " + guid.ToString("X16"));

            Coords3 coords = gr2.ReadCoords3();
            sb.AppendLine("Start point " + coords.GetCoords());

            uint time = gr2.ReadUInt32();
            sb.AppendLine("Time " + time);

            byte unk = gr2.ReadByte();
            sb.AppendLine("unk_byte " + unk);

            switch (unk)
            {
                case 0: // обычный пакет
                    break;
                case 1: // стоп, конец пакета...
                    sb.AppendLine("stop");
                    return true;
                case 2:
                    Coords3 point = gr2.ReadCoords3();
                    sb.AppendLine("unk point " + point.GetCoords());
                    break;
                case 3: // чей-то гуид, скорее всего таргета...
                    ulong target_guid = gr2.ReadUInt64();
                    sb.AppendLine("GUID unknown " + target_guid.ToString("X16"));
                    break;
                case 4: // похоже на ориентацию...
                    float orientation = gr2.ReadSingle();
                    sb.AppendLine("Orientation " + orientation.ToString().Replace(",", "."));
                    break;
                default:
                    swe.WriteLine("Error in position " + gr.BaseStream.Position.ToString("X2"));
                    swe.WriteLine("unknown unk " + unk);
                    break;
            }

            Flags flags = (Flags)gr2.ReadUInt32();
            sb.AppendLine("Flags " + flags);

            uint movetime = gr2.ReadUInt32();
            sb.AppendLine("MoveTime " + movetime);

            uint points = gr2.ReadUInt32();
            sb.AppendLine("Points " + points);

            List<Node> nodes = new List<Node>((int)points);

            if ((flags & Flags.flag10) != 0) // 0x200
            {
                sb.AppendLine("Taxi");
                for (uint i = 0; i < points; i++)
                {
                    Node node = new Node();
                    node.x = gr2.ReadSingle();
                    node.y = gr2.ReadSingle();
                    node.z = gr2.ReadSingle();
                    nodes.Add(node);
                    //Coords3 path = gr2.ReadCoords3();
                    //sb.AppendLine("Path point" + i + ": " + path.GetCoords());
                }
            }
            else
            {
                if ((flags & Flags.flag09) == 0 && (flags & Flags.flag10) == 0 && flags != 0)
                {
                    swe.WriteLine("Unknown flags " + flags);
                }

                if ((flags & Flags.flag09) != 0)
                    sb.AppendLine("Running");

                Coords3 end = gr2.ReadCoords3();
                sb.AppendLine("End point " + end.GetCoords());

                for (uint i = 0; i < (points - 1); i++)
                {
                    int mask = gr2.ReadInt32();
                    sb.AppendLine("shift mask" + i + " " + mask.ToString("X8"));

                    int temp1, temp2, temp3;
                    temp1 = (mask & 0x07FF) << 0x15;
                    temp2 = ((mask >> 0x0B) & 0x07FF) << 0x15;
                    temp3 = (mask >> 0x16) << 0x16;
                    temp1 >>= 0x15;
                    temp2 >>= 0x15;
                    temp3 >>= 0x16;
                    float x = temp1 * 0.25f;
                    float y = temp2 * 0.25f;
                    float z = temp3 * 0.25f;
                    sb.AppendLine("shift is " + x + " " + y + " " + z + ".");
                }
            }

            if ((flags & Flags.flag10) != 0)
            {
                StreamWriter sw = new StreamWriter("taxiinfo.txt", true);
                sw.WriteLine("GUID: 0x" + guid.ToString("X16"));
                sw.WriteLine(string.Format("Position: {0} {1} {2}", coords.X, coords.Y, coords.Z));
                sw.WriteLine("Time: " + time);
                sw.WriteLine("Movetime: " + movetime);
                sw.WriteLine("Nodes: " + points);
                for (int i = 0; i < points; i++)
                    sw.WriteLine(string.Format("Node {0}: {1} {2} {3}", i, nodes[i].x, nodes[i].y, nodes[i].z));

                uint mangos_time = 0;

                float len = 0, xd, yd, zd;

                /*xd = nodes[0].x - coords.X;
                yd = nodes[0].y - coords.Y;
                zd = nodes[0].z - coords.Z;
                len += (float)Math.Sqrt((xd * xd + yd * yd + zd * zd));*/

                for (int i = 1; i < points; i++)
                {
                    xd = nodes[i].x - nodes[i - 1].x;
                    yd = nodes[i].y - nodes[i - 1].y;
                    zd = nodes[i].z - nodes[i - 1].z;
                    len += (float)Math.Sqrt((xd * xd + yd * yd + zd * zd));
                }

                mangos_time = (uint)(len * 33.360f);    // 33.373f / 33.336

                sw.WriteLine("Mangostime 3D: " + mangos_time);

                mangos_time = 0;
                len = 0;

                for (int i = 1; i < points; i++)
                {
                    xd = nodes[i].x - nodes[i - 1].x;
                    yd = nodes[i].y - nodes[i - 1].y;
                    len += (float)Math.Sqrt((xd * xd + yd * yd));
                }

                mangos_time = (uint)(len * 33.360f);

                sw.WriteLine("Mangostime 2D: " + mangos_time);
                sw.WriteLine();

                sw.Flush();
                sw.Close();
            }
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="gr"></param>
        /// <param name="gr2"></param>
        /// <param name="sb"></param>
        /// <param name="swe"></param>
        /// <returns></returns>
        public static bool ParseInitialSpellsOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            sb.AppendLine("Packet offset " + gr.BaseStream.Position.ToString("X2"));
            sb.AppendLine("Opcode SMSG_INITIAL_SPELLS (0x012A)");

            byte unk1 = gr2.ReadByte();

            sb.AppendLine("unk byte " + unk1);

            ushort spells_count = gr2.ReadUInt16();
            sb.AppendLine("Spells count " + spells_count);
            for (ushort i = 0; i < spells_count; i++)
            {
                ushort spellid = gr2.ReadUInt16();
                ushort slotid = gr2.ReadUInt16();
                sb.AppendLine("Spell ID " + spellid + ", slot " + slotid.ToString("X2"));
            }

            ushort cooldowns_count = gr2.ReadUInt16();
            sb.AppendLine("Cooldowns count " + cooldowns_count);
            for (ushort i = 0; i < cooldowns_count; i++)
            {
                ushort spellid = gr2.ReadUInt16();
                ushort itemid = gr2.ReadUInt16();
                ushort spellcategory = gr2.ReadUInt16();
                uint cooldown1 = gr2.ReadUInt32();
                uint cooldown2 = gr2.ReadUInt32();
                sb.AppendLine("Spell Cooldown: spell id " + spellid + ", itemid " + itemid + ", spellcategory " + spellcategory + ", cooldown1 " + cooldown1 + ", cooldown2 " + cooldown2);
            }
            return true;
        }
        public static bool ParseCorpseQueryOpcode(GenericReader gr, GenericReader gr2, StringBuilder sb, StreamWriter swe, byte direction)
        {
            if (direction == 0)  // client packet
                return false;

            StreamWriter sw = new StreamWriter("corpse_query.log", true, Encoding.ASCII);

            sw.WriteLine("Packet offset {0}", gr.BaseStream.Position.ToString("X2"));
            sw.WriteLine("Opcode MSG_CORPSE_QUERY (0x0216)");

            byte unk = gr2.ReadByte();
            sw.WriteLine("unk {0}", unk);
            if (unk > 0)
            {
                uint mapid1 = gr2.ReadUInt32();
                float x = gr2.ReadSingle();
                float y = gr2.ReadSingle();
                float z = gr2.ReadSingle();
                uint mapid2 = gr2.ReadUInt32();
                sw.WriteLine("map {0}, pos {1} {2} {3}", mapid1, x, y, z);
                sw.WriteLine("map2 {0}", mapid2);
            }

            if (gr2.BaseStream.Position == gr2.BaseStream.Length)
                sw.WriteLine("parsed: ok...");
            else
                sw.WriteLine("parsed: error...");

            sw.WriteLine();
            sw.Flush();
            sw.Close();

            return true;
        }