corrade-vassal – Rev 1

Subversion Repositories:
Rev:
/*
 * Copyright (c) 2006-2014, openmetaverse.org
 * All rights reserved.
 *
 * - Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Neither the name of the Second Life Reverse Engineering Team nor the names
 *   of its contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Text;
using OpenMetaverse;

namespace OpenMetaverse
{
    /// <summary>
    /// 
    /// </summary>
    public enum PacketFrequency : byte
    {
        /// <summary></summary>
        Low,
        /// <summary></summary>
        Medium,
        /// <summary></summary>
        High
    }
}
    
namespace OpenMetaverse.Packets
{
    /// <summary>
    /// Thrown when a packet could not be successfully deserialized
    /// </summary>
    public class MalformedDataException : ApplicationException
    {
        /// <summary>
        /// Default constructor
        /// </summary>
        public MalformedDataException() { }

        /// <summary>
        /// Constructor that takes an additional error message
        /// </summary>
        /// <param name="Message">An error message to attach to this exception</param>
        public MalformedDataException(string Message)
            : base(Message)
        {
            this.Source = "Packet decoding";
        }
    }
    
    /// <summary>
    /// The header of a message template packet. Holds packet flags, sequence
    /// number, packet ID, and any ACKs that will be appended at the end of
    /// the packet
    /// </summary>
    public struct Header
    {
        public bool Reliable;
        public bool Resent;
        public bool Zerocoded;
        public bool AppendedAcks;
        public uint Sequence;
        public ushort ID;
        public PacketFrequency Frequency;
        public uint[] AckList;

        public void ToBytes(byte[] bytes, ref int i)
        {
            byte flags = 0;
            if (Reliable) flags |= Helpers.MSG_RELIABLE;
            if (Resent) flags |= Helpers.MSG_RESENT;
            if (Zerocoded) flags |= Helpers.MSG_ZEROCODED;
            if (AppendedAcks) flags |= Helpers.MSG_APPENDED_ACKS;

            // Flags
            bytes[i++] = flags;
            
            // Sequence number
            Utils.UIntToBytesBig(Sequence, bytes, i);
            i += 4;

            // Extra byte
            bytes[i++] = 0;

            // Packet ID
            switch (Frequency)
            {
                case PacketFrequency.High:
                    // 1 byte ID
                    bytes[i++] = (byte)ID;
                    break;
                case PacketFrequency.Medium:
                    // 2 byte ID
                    bytes[i++] = 0xFF;
                    bytes[i++] = (byte)ID;
                    break;
                case PacketFrequency.Low:
                    // 4 byte ID
                    bytes[i++] = 0xFF;
                    bytes[i++] = 0xFF;
                    Utils.UInt16ToBytesBig(ID, bytes, i);
                    i += 2;
                    break;
            }
        }

        public void FromBytes(byte[] bytes, ref int pos, ref int packetEnd)
        {
            this = BuildHeader(bytes, ref pos, ref packetEnd);
        }

        /// <summary>
        /// Convert the AckList to a byte array, used for packet serializing
        /// </summary>
        /// <param name="bytes">Reference to the target byte array</param>
        /// <param name="i">Beginning position to start writing to in the byte
        /// array, will be updated with the ending position of the ACK list</param>
        public void AcksToBytes(byte[] bytes, ref int i)
        {
            foreach (uint ack in AckList)
            {
                Utils.UIntToBytesBig(ack, bytes, i);
                i += 4;
            }
            if (AckList.Length > 0) { bytes[i++] = (byte)AckList.Length; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="pos"></param>
        /// <param name="packetEnd"></param>
        /// <returns></returns>
        public static Header BuildHeader(byte[] bytes, ref int pos, ref int packetEnd)
        {
            Header header;
            byte flags = bytes[pos];

            header.AppendedAcks = (flags & Helpers.MSG_APPENDED_ACKS) != 0;
            header.Reliable = (flags & Helpers.MSG_RELIABLE) != 0;
            header.Resent = (flags & Helpers.MSG_RESENT) != 0;
            header.Zerocoded = (flags & Helpers.MSG_ZEROCODED) != 0;
            header.Sequence = (uint)((bytes[pos + 1] << 24) + (bytes[pos + 2] << 16) + (bytes[pos + 3] << 8) + bytes[pos + 4]);

            // Set the frequency and packet ID number
            if (bytes[pos + 6] == 0xFF)
            {
                if (bytes[pos + 7] == 0xFF)
                {
                    header.Frequency = PacketFrequency.Low;
                    if (header.Zerocoded && bytes[pos + 8] == 0)
                        header.ID = bytes[pos + 10];
                    else
                        header.ID = (ushort)((bytes[pos + 8] << 8) + bytes[pos + 9]);
                    
                    pos += 10;
                }
                else
                {
                    header.Frequency = PacketFrequency.Medium;
                    header.ID = bytes[pos + 7];

                    pos += 8;
                }
            }
            else
            {
                header.Frequency = PacketFrequency.High;
                header.ID = bytes[pos + 6];

                pos += 7;
            }

            header.AckList = null;
            CreateAckList(ref header, bytes, ref packetEnd);

            return header;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="header"></param>
        /// <param name="bytes"></param>
        /// <param name="packetEnd"></param>
        static void CreateAckList(ref Header header, byte[] bytes, ref int packetEnd)
        {
            if (header.AppendedAcks)
            {
                int count = bytes[packetEnd--];
                header.AckList = new uint[count];
                
                for (int i = 0; i < count; i++)
                {
                    header.AckList[i] = (uint)(
                        (bytes[(packetEnd - i * 4) - 3] << 24) |
                        (bytes[(packetEnd - i * 4) - 2] << 16) |
                        (bytes[(packetEnd - i * 4) - 1] <<  8) |
                        (bytes[(packetEnd - i * 4)    ]));
                }

                packetEnd -= (count * 4);
            }
        }
    }

    /// <summary>
    /// A block of data in a packet. Packets are composed of one or more blocks,
    /// each block containing one or more fields
    /// </summary>
    public abstract class PacketBlock
    {
        /// <summary>Current length of the data in this packet</summary>
        public abstract int Length { get; }

        /// <summary>
        /// Create a block from a byte array
        /// </summary>
        /// <param name="bytes">Byte array containing the serialized block</param>
        /// <param name="i">Starting position of the block in the byte array.
        /// This will point to the data after the end of the block when the
        /// call returns</param>
        public abstract void FromBytes(byte[] bytes, ref int i);

        /// <summary>
        /// Serialize this block into a byte array
        /// </summary>
        /// <param name="bytes">Byte array to serialize this block into</param>
        /// <param name="i">Starting position in the byte array to serialize to.
        /// This will point to the position directly after the end of the
        /// serialized block when the call returns</param>
        public abstract void ToBytes(byte[] bytes, ref int i);
    }

    public enum PacketType
    {
        /// <summary>A generic value, not an actual packet type</summary>
        Default,
        TestMessage = 65537,
        UseCircuitCode = 65539,
        TelehubInfo = 65546,
        EconomyDataRequest = 65560,
        EconomyData = 65561,
        AvatarPickerRequest = 65562,
        AvatarPickerReply = 65564,
        PlacesQuery = 65565,
        PlacesReply = 65566,
        DirFindQuery = 65567,
        DirPlacesQuery = 65569,
        DirPlacesReply = 65571,
        DirPeopleReply = 65572,
        DirEventsReply = 65573,
        DirGroupsReply = 65574,
        DirClassifiedQuery = 65575,
        DirClassifiedReply = 65577,
        AvatarClassifiedReply = 65578,
        ClassifiedInfoRequest = 65579,
        ClassifiedInfoReply = 65580,
        ClassifiedInfoUpdate = 65581,
        ClassifiedDelete = 65582,
        ClassifiedGodDelete = 65583,
        DirLandQuery = 65584,
        DirLandReply = 65586,
        DirPopularQuery = 65587,
        DirPopularReply = 65589,
        ParcelInfoRequest = 65590,
        ParcelInfoReply = 65591,
        ParcelObjectOwnersRequest = 65592,
        ParcelObjectOwnersReply = 65593,
        GroupNoticesListRequest = 65594,
        GroupNoticesListReply = 65595,
        GroupNoticeRequest = 65596,
        TeleportRequest = 65598,
        TeleportLocationRequest = 65599,
        TeleportLocal = 65600,
        TeleportLandmarkRequest = 65601,
        TeleportProgress = 65602,
        TeleportFinish = 65605,
        StartLure = 65606,
        TeleportLureRequest = 65607,
        TeleportCancel = 65608,
        TeleportStart = 65609,
        TeleportFailed = 65610,
        Undo = 65611,
        Redo = 65612,
        UndoLand = 65613,
        AgentPause = 65614,
        AgentResume = 65615,
        ChatFromViewer = 65616,
        AgentThrottle = 65617,
        AgentFOV = 65618,
        AgentHeightWidth = 65619,
        AgentSetAppearance = 65620,
        AgentQuitCopy = 65621,
        ImageNotInDatabase = 65622,
        RebakeAvatarTextures = 65623,
        SetAlwaysRun = 65624,
        ObjectDelete = 65625,
        ObjectDuplicate = 65626,
        ObjectDuplicateOnRay = 65627,
        ObjectScale = 65628,
        ObjectRotation = 65629,
        ObjectFlagUpdate = 65630,
        ObjectClickAction = 65631,
        ObjectImage = 65632,
        ObjectMaterial = 65633,
        ObjectShape = 65634,
        ObjectExtraParams = 65635,
        ObjectOwner = 65636,
        ObjectGroup = 65637,
        ObjectBuy = 65638,
        BuyObjectInventory = 65639,
        DerezContainer = 65640,
        ObjectPermissions = 65641,
        ObjectSaleInfo = 65642,
        ObjectName = 65643,
        ObjectDescription = 65644,
        ObjectCategory = 65645,
        ObjectSelect = 65646,
        ObjectDeselect = 65647,
        ObjectAttach = 65648,
        ObjectDetach = 65649,
        ObjectDrop = 65650,
        ObjectLink = 65651,
        ObjectDelink = 65652,
        ObjectGrab = 65653,
        ObjectGrabUpdate = 65654,
        ObjectDeGrab = 65655,
        ObjectSpinStart = 65656,
        ObjectSpinUpdate = 65657,
        ObjectSpinStop = 65658,
        ObjectExportSelected = 65659,
        ModifyLand = 65660,
        VelocityInterpolateOn = 65661,
        VelocityInterpolateOff = 65662,
        StateSave = 65663,
        ReportAutosaveCrash = 65664,
        SimWideDeletes = 65665,
        TrackAgent = 65666,
        ViewerStats = 65667,
        ScriptAnswerYes = 65668,
        UserReport = 65669,
        AlertMessage = 65670,
        AgentAlertMessage = 65671,
        MeanCollisionAlert = 65672,
        ViewerFrozenMessage = 65673,
        HealthMessage = 65674,
        ChatFromSimulator = 65675,
        SimStats = 65676,
        RequestRegionInfo = 65677,
        RegionInfo = 65678,
        GodUpdateRegionInfo = 65679,
        RegionHandshake = 65684,
        RegionHandshakeReply = 65685,
        SimulatorViewerTimeMessage = 65686,
        EnableSimulator = 65687,
        DisableSimulator = 65688,
        TransferRequest = 65689,
        TransferInfo = 65690,
        TransferAbort = 65691,
        RequestXfer = 65692,
        AbortXfer = 65693,
        AvatarAppearance = 65694,
        SetFollowCamProperties = 65695,
        ClearFollowCamProperties = 65696,
        RequestPayPrice = 65697,
        PayPriceReply = 65698,
        KickUser = 65699,
        GodKickUser = 65701,
        EjectUser = 65703,
        FreezeUser = 65704,
        AvatarPropertiesRequest = 65705,
        AvatarPropertiesReply = 65707,
        AvatarInterestsReply = 65708,
        AvatarGroupsReply = 65709,
        AvatarPropertiesUpdate = 65710,
        AvatarInterestsUpdate = 65711,
        AvatarNotesReply = 65712,
        AvatarNotesUpdate = 65713,
        AvatarPicksReply = 65714,
        EventInfoRequest = 65715,
        EventInfoReply = 65716,
        EventNotificationAddRequest = 65717,
        EventNotificationRemoveRequest = 65718,
        EventGodDelete = 65719,
        PickInfoReply = 65720,
        PickInfoUpdate = 65721,
        PickDelete = 65722,
        PickGodDelete = 65723,
        ScriptQuestion = 65724,
        ScriptControlChange = 65725,
        ScriptDialog = 65726,
        ScriptDialogReply = 65727,
        ForceScriptControlRelease = 65728,
        RevokePermissions = 65729,
        LoadURL = 65730,
        ScriptTeleportRequest = 65731,
        ParcelOverlay = 65732,
        ParcelPropertiesRequestByID = 65733,
        ParcelPropertiesUpdate = 65734,
        ParcelReturnObjects = 65735,
        ParcelSetOtherCleanTime = 65736,
        ParcelDisableObjects = 65737,
        ParcelSelectObjects = 65738,
        EstateCovenantRequest = 65739,
        EstateCovenantReply = 65740,
        ForceObjectSelect = 65741,
        ParcelBuyPass = 65742,
        ParcelDeedToGroup = 65743,
        ParcelReclaim = 65744,
        ParcelClaim = 65745,
        ParcelJoin = 65746,
        ParcelDivide = 65747,
        ParcelRelease = 65748,
        ParcelBuy = 65749,
        ParcelGodForceOwner = 65750,
        ParcelAccessListRequest = 65751,
        ParcelAccessListReply = 65752,
        ParcelAccessListUpdate = 65753,
        ParcelDwellRequest = 65754,
        ParcelDwellReply = 65755,
        ParcelGodMarkAsContent = 65763,
        ViewerStartAuction = 65764,
        UUIDNameRequest = 65771,
        UUIDNameReply = 65772,
        UUIDGroupNameRequest = 65773,
        UUIDGroupNameReply = 65774,
        ChildAgentDying = 65776,
        ChildAgentUnknown = 65777,
        GetScriptRunning = 65779,
        ScriptRunningReply = 65780,
        SetScriptRunning = 65781,
        ScriptReset = 65782,
        ScriptSensorRequest = 65783,
        ScriptSensorReply = 65784,
        CompleteAgentMovement = 65785,
        AgentMovementComplete = 65786,
        LogoutRequest = 65788,
        LogoutReply = 65789,
        ImprovedInstantMessage = 65790,
        RetrieveInstantMessages = 65791,
        FindAgent = 65792,
        RequestGodlikePowers = 65793,
        GrantGodlikePowers = 65794,
        GodlikeMessage = 65795,
        EstateOwnerMessage = 65796,
        GenericMessage = 65797,
        MuteListRequest = 65798,
        UpdateMuteListEntry = 65799,
        RemoveMuteListEntry = 65800,
        CopyInventoryFromNotecard = 65801,
        UpdateInventoryItem = 65802,
        UpdateCreateInventoryItem = 65803,
        MoveInventoryItem = 65804,
        CopyInventoryItem = 65805,
        RemoveInventoryItem = 65806,
        ChangeInventoryItemFlags = 65807,
        SaveAssetIntoInventory = 65808,
        CreateInventoryFolder = 65809,
        UpdateInventoryFolder = 65810,
        MoveInventoryFolder = 65811,
        RemoveInventoryFolder = 65812,
        FetchInventoryDescendents = 65813,
        InventoryDescendents = 65814,
        FetchInventory = 65815,
        FetchInventoryReply = 65816,
        BulkUpdateInventory = 65817,
        RemoveInventoryObjects = 65820,
        PurgeInventoryDescendents = 65821,
        UpdateTaskInventory = 65822,
        RemoveTaskInventory = 65823,
        MoveTaskInventory = 65824,
        RequestTaskInventory = 65825,
        ReplyTaskInventory = 65826,
        DeRezObject = 65827,
        DeRezAck = 65828,
        RezObject = 65829,
        RezObjectFromNotecard = 65830,
        AcceptFriendship = 65833,
        DeclineFriendship = 65834,
        TerminateFriendship = 65836,
        OfferCallingCard = 65837,
        AcceptCallingCard = 65838,
        DeclineCallingCard = 65839,
        RezScript = 65840,
        CreateInventoryItem = 65841,
        CreateLandmarkForEvent = 65842,
        RegionHandleRequest = 65845,
        RegionIDAndHandleReply = 65846,
        MoneyTransferRequest = 65847,
        MoneyBalanceRequest = 65849,
        MoneyBalanceReply = 65850,
        RoutedMoneyBalanceReply = 65851,
        ActivateGestures = 65852,
        DeactivateGestures = 65853,
        MuteListUpdate = 65854,
        UseCachedMuteList = 65855,
        GrantUserRights = 65856,
        ChangeUserRights = 65857,
        OnlineNotification = 65858,
        OfflineNotification = 65859,
        SetStartLocationRequest = 65860,
        AssetUploadRequest = 65869,
        AssetUploadComplete = 65870,
        CreateGroupRequest = 65875,
        CreateGroupReply = 65876,
        UpdateGroupInfo = 65877,
        GroupRoleChanges = 65878,
        JoinGroupRequest = 65879,
        JoinGroupReply = 65880,
        EjectGroupMemberRequest = 65881,
        EjectGroupMemberReply = 65882,
        LeaveGroupRequest = 65883,
        LeaveGroupReply = 65884,
        InviteGroupRequest = 65885,
        GroupProfileRequest = 65887,
        GroupProfileReply = 65888,
        GroupAccountSummaryRequest = 65889,
        GroupAccountSummaryReply = 65890,
        GroupAccountDetailsRequest = 65891,
        GroupAccountDetailsReply = 65892,
        GroupAccountTransactionsRequest = 65893,
        GroupAccountTransactionsReply = 65894,
        GroupActiveProposalsRequest = 65895,
        GroupActiveProposalItemReply = 65896,
        GroupVoteHistoryRequest = 65897,
        GroupVoteHistoryItemReply = 65898,
        StartGroupProposal = 65899,
        GroupProposalBallot = 65900,
        GroupMembersRequest = 65902,
        GroupMembersReply = 65903,
        ActivateGroup = 65904,
        SetGroupContribution = 65905,
        SetGroupAcceptNotices = 65906,
        GroupRoleDataRequest = 65907,
        GroupRoleDataReply = 65908,
        GroupRoleMembersRequest = 65909,
        GroupRoleMembersReply = 65910,
        GroupTitlesRequest = 65911,
        GroupTitlesReply = 65912,
        GroupTitleUpdate = 65913,
        GroupRoleUpdate = 65914,
        LiveHelpGroupRequest = 65915,
        LiveHelpGroupReply = 65916,
        AgentWearablesRequest = 65917,
        AgentWearablesUpdate = 65918,
        AgentIsNowWearing = 65919,
        AgentCachedTexture = 65920,
        AgentCachedTextureResponse = 65921,
        AgentDataUpdateRequest = 65922,
        AgentDataUpdate = 65923,
        GroupDataUpdate = 65924,
        AgentGroupDataUpdate = 65925,
        AgentDropGroup = 65926,
        RezSingleAttachmentFromInv = 65931,
        RezMultipleAttachmentsFromInv = 65932,
        DetachAttachmentIntoInv = 65933,
        CreateNewOutfitAttachments = 65934,
        UserInfoRequest = 65935,
        UserInfoReply = 65936,
        UpdateUserInfo = 65937,
        InitiateDownload = 65939,
        MapLayerRequest = 65941,
        MapLayerReply = 65942,
        MapBlockRequest = 65943,
        MapNameRequest = 65944,
        MapBlockReply = 65945,
        MapItemRequest = 65946,
        MapItemReply = 65947,
        SendPostcard = 65948,
        ParcelMediaCommandMessage = 65955,
        ParcelMediaUpdate = 65956,
        LandStatRequest = 65957,
        LandStatReply = 65958,
        Error = 65959,
        ObjectIncludeInSearch = 65960,
        RezRestoreToWorld = 65961,
        LinkInventoryItem = 65962,
        PacketAck = 131067,
        OpenCircuit = 131068,
        CloseCircuit = 131069,
        ObjectAdd = 131073,
        MultipleObjectUpdate = 131074,
        RequestMultipleObjects = 131075,
        ObjectPosition = 131076,
        RequestObjectPropertiesFamily = 131077,
        CoarseLocationUpdate = 131078,
        CrossedRegion = 131079,
        ConfirmEnableSimulator = 131080,
        ObjectProperties = 131081,
        ObjectPropertiesFamily = 131082,
        ParcelPropertiesRequest = 131083,
        AttachedSound = 131085,
        AttachedSoundGainChange = 131086,
        PreloadSound = 131087,
        ViewerEffect = 131089,
        StartPingCheck = 196609,
        CompletePingCheck = 196610,
        AgentUpdate = 196612,
        AgentAnimation = 196613,
        AgentRequestSit = 196614,
        AgentSit = 196615,
        RequestImage = 196616,
        ImageData = 196617,
        ImagePacket = 196618,
        LayerData = 196619,
        ObjectUpdate = 196620,
        ObjectUpdateCompressed = 196621,
        ObjectUpdateCached = 196622,
        ImprovedTerseObjectUpdate = 196623,
        KillObject = 196624,
        TransferPacket = 196625,
        SendXferPacket = 196626,
        ConfirmXferPacket = 196627,
        AvatarAnimation = 196628,
        AvatarSitResponse = 196629,
        CameraConstraint = 196630,
        ParcelProperties = 196631,
        ChildAgentUpdate = 196633,
        ChildAgentAlive = 196634,
        ChildAgentPositionUpdate = 196635,
        SoundTrigger = 196637,
    }

    public abstract partial class Packet
    {
        public const int MTU = 1200;

        public Header Header;
        public bool HasVariableBlocks;
        public PacketType Type;
        public abstract int Length { get; }
        public abstract void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer);
        public abstract void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd);
        public abstract byte[] ToBytes();
        public abstract byte[][] ToBytesMultiple();

        public static PacketType GetType(ushort id, PacketFrequency frequency)
        {
            switch (frequency)
            {
                case PacketFrequency.Low:
                    switch (id)
                    {
                        case 1: return PacketType.TestMessage;
                        case 3: return PacketType.UseCircuitCode;
                        case 10: return PacketType.TelehubInfo;
                        case 24: return PacketType.EconomyDataRequest;
                        case 25: return PacketType.EconomyData;
                        case 26: return PacketType.AvatarPickerRequest;
                        case 28: return PacketType.AvatarPickerReply;
                        case 29: return PacketType.PlacesQuery;
                        case 30: return PacketType.PlacesReply;
                        case 31: return PacketType.DirFindQuery;
                        case 33: return PacketType.DirPlacesQuery;
                        case 35: return PacketType.DirPlacesReply;
                        case 36: return PacketType.DirPeopleReply;
                        case 37: return PacketType.DirEventsReply;
                        case 38: return PacketType.DirGroupsReply;
                        case 39: return PacketType.DirClassifiedQuery;
                        case 41: return PacketType.DirClassifiedReply;
                        case 42: return PacketType.AvatarClassifiedReply;
                        case 43: return PacketType.ClassifiedInfoRequest;
                        case 44: return PacketType.ClassifiedInfoReply;
                        case 45: return PacketType.ClassifiedInfoUpdate;
                        case 46: return PacketType.ClassifiedDelete;
                        case 47: return PacketType.ClassifiedGodDelete;
                        case 48: return PacketType.DirLandQuery;
                        case 50: return PacketType.DirLandReply;
                        case 51: return PacketType.DirPopularQuery;
                        case 53: return PacketType.DirPopularReply;
                        case 54: return PacketType.ParcelInfoRequest;
                        case 55: return PacketType.ParcelInfoReply;
                        case 56: return PacketType.ParcelObjectOwnersRequest;
                        case 57: return PacketType.ParcelObjectOwnersReply;
                        case 58: return PacketType.GroupNoticesListRequest;
                        case 59: return PacketType.GroupNoticesListReply;
                        case 60: return PacketType.GroupNoticeRequest;
                        case 62: return PacketType.TeleportRequest;
                        case 63: return PacketType.TeleportLocationRequest;
                        case 64: return PacketType.TeleportLocal;
                        case 65: return PacketType.TeleportLandmarkRequest;
                        case 66: return PacketType.TeleportProgress;
                        case 69: return PacketType.TeleportFinish;
                        case 70: return PacketType.StartLure;
                        case 71: return PacketType.TeleportLureRequest;
                        case 72: return PacketType.TeleportCancel;
                        case 73: return PacketType.TeleportStart;
                        case 74: return PacketType.TeleportFailed;
                        case 75: return PacketType.Undo;
                        case 76: return PacketType.Redo;
                        case 77: return PacketType.UndoLand;
                        case 78: return PacketType.AgentPause;
                        case 79: return PacketType.AgentResume;
                        case 80: return PacketType.ChatFromViewer;
                        case 81: return PacketType.AgentThrottle;
                        case 82: return PacketType.AgentFOV;
                        case 83: return PacketType.AgentHeightWidth;
                        case 84: return PacketType.AgentSetAppearance;
                        case 85: return PacketType.AgentQuitCopy;
                        case 86: return PacketType.ImageNotInDatabase;
                        case 87: return PacketType.RebakeAvatarTextures;
                        case 88: return PacketType.SetAlwaysRun;
                        case 89: return PacketType.ObjectDelete;
                        case 90: return PacketType.ObjectDuplicate;
                        case 91: return PacketType.ObjectDuplicateOnRay;
                        case 92: return PacketType.ObjectScale;
                        case 93: return PacketType.ObjectRotation;
                        case 94: return PacketType.ObjectFlagUpdate;
                        case 95: return PacketType.ObjectClickAction;
                        case 96: return PacketType.ObjectImage;
                        case 97: return PacketType.ObjectMaterial;
                        case 98: return PacketType.ObjectShape;
                        case 99: return PacketType.ObjectExtraParams;
                        case 100: return PacketType.ObjectOwner;
                        case 101: return PacketType.ObjectGroup;
                        case 102: return PacketType.ObjectBuy;
                        case 103: return PacketType.BuyObjectInventory;
                        case 104: return PacketType.DerezContainer;
                        case 105: return PacketType.ObjectPermissions;
                        case 106: return PacketType.ObjectSaleInfo;
                        case 107: return PacketType.ObjectName;
                        case 108: return PacketType.ObjectDescription;
                        case 109: return PacketType.ObjectCategory;
                        case 110: return PacketType.ObjectSelect;
                        case 111: return PacketType.ObjectDeselect;
                        case 112: return PacketType.ObjectAttach;
                        case 113: return PacketType.ObjectDetach;
                        case 114: return PacketType.ObjectDrop;
                        case 115: return PacketType.ObjectLink;
                        case 116: return PacketType.ObjectDelink;
                        case 117: return PacketType.ObjectGrab;
                        case 118: return PacketType.ObjectGrabUpdate;
                        case 119: return PacketType.ObjectDeGrab;
                        case 120: return PacketType.ObjectSpinStart;
                        case 121: return PacketType.ObjectSpinUpdate;
                        case 122: return PacketType.ObjectSpinStop;
                        case 123: return PacketType.ObjectExportSelected;
                        case 124: return PacketType.ModifyLand;
                        case 125: return PacketType.VelocityInterpolateOn;
                        case 126: return PacketType.VelocityInterpolateOff;
                        case 127: return PacketType.StateSave;
                        case 128: return PacketType.ReportAutosaveCrash;
                        case 129: return PacketType.SimWideDeletes;
                        case 130: return PacketType.TrackAgent;
                        case 131: return PacketType.ViewerStats;
                        case 132: return PacketType.ScriptAnswerYes;
                        case 133: return PacketType.UserReport;
                        case 134: return PacketType.AlertMessage;
                        case 135: return PacketType.AgentAlertMessage;
                        case 136: return PacketType.MeanCollisionAlert;
                        case 137: return PacketType.ViewerFrozenMessage;
                        case 138: return PacketType.HealthMessage;
                        case 139: return PacketType.ChatFromSimulator;
                        case 140: return PacketType.SimStats;
                        case 141: return PacketType.RequestRegionInfo;
                        case 142: return PacketType.RegionInfo;
                        case 143: return PacketType.GodUpdateRegionInfo;
                        case 148: return PacketType.RegionHandshake;
                        case 149: return PacketType.RegionHandshakeReply;
                        case 150: return PacketType.SimulatorViewerTimeMessage;
                        case 151: return PacketType.EnableSimulator;
                        case 152: return PacketType.DisableSimulator;
                        case 153: return PacketType.TransferRequest;
                        case 154: return PacketType.TransferInfo;
                        case 155: return PacketType.TransferAbort;
                        case 156: return PacketType.RequestXfer;
                        case 157: return PacketType.AbortXfer;
                        case 158: return PacketType.AvatarAppearance;
                        case 159: return PacketType.SetFollowCamProperties;
                        case 160: return PacketType.ClearFollowCamProperties;
                        case 161: return PacketType.RequestPayPrice;
                        case 162: return PacketType.PayPriceReply;
                        case 163: return PacketType.KickUser;
                        case 165: return PacketType.GodKickUser;
                        case 167: return PacketType.EjectUser;
                        case 168: return PacketType.FreezeUser;
                        case 169: return PacketType.AvatarPropertiesRequest;
                        case 171: return PacketType.AvatarPropertiesReply;
                        case 172: return PacketType.AvatarInterestsReply;
                        case 173: return PacketType.AvatarGroupsReply;
                        case 174: return PacketType.AvatarPropertiesUpdate;
                        case 175: return PacketType.AvatarInterestsUpdate;
                        case 176: return PacketType.AvatarNotesReply;
                        case 177: return PacketType.AvatarNotesUpdate;
                        case 178: return PacketType.AvatarPicksReply;
                        case 179: return PacketType.EventInfoRequest;
                        case 180: return PacketType.EventInfoReply;
                        case 181: return PacketType.EventNotificationAddRequest;
                        case 182: return PacketType.EventNotificationRemoveRequest;
                        case 183: return PacketType.EventGodDelete;
                        case 184: return PacketType.PickInfoReply;
                        case 185: return PacketType.PickInfoUpdate;
                        case 186: return PacketType.PickDelete;
                        case 187: return PacketType.PickGodDelete;
                        case 188: return PacketType.ScriptQuestion;
                        case 189: return PacketType.ScriptControlChange;
                        case 190: return PacketType.ScriptDialog;
                        case 191: return PacketType.ScriptDialogReply;
                        case 192: return PacketType.ForceScriptControlRelease;
                        case 193: return PacketType.RevokePermissions;
                        case 194: return PacketType.LoadURL;
                        case 195: return PacketType.ScriptTeleportRequest;
                        case 196: return PacketType.ParcelOverlay;
                        case 197: return PacketType.ParcelPropertiesRequestByID;
                        case 198: return PacketType.ParcelPropertiesUpdate;
                        case 199: return PacketType.ParcelReturnObjects;
                        case 200: return PacketType.ParcelSetOtherCleanTime;
                        case 201: return PacketType.ParcelDisableObjects;
                        case 202: return PacketType.ParcelSelectObjects;
                        case 203: return PacketType.EstateCovenantRequest;
                        case 204: return PacketType.EstateCovenantReply;
                        case 205: return PacketType.ForceObjectSelect;
                        case 206: return PacketType.ParcelBuyPass;
                        case 207: return PacketType.ParcelDeedToGroup;
                        case 208: return PacketType.ParcelReclaim;
                        case 209: return PacketType.ParcelClaim;
                        case 210: return PacketType.ParcelJoin;
                        case 211: return PacketType.ParcelDivide;
                        case 212: return PacketType.ParcelRelease;
                        case 213: return PacketType.ParcelBuy;
                        case 214: return PacketType.ParcelGodForceOwner;
                        case 215: return PacketType.ParcelAccessListRequest;
                        case 216: return PacketType.ParcelAccessListReply;
                        case 217: return PacketType.ParcelAccessListUpdate;
                        case 218: return PacketType.ParcelDwellRequest;
                        case 219: return PacketType.ParcelDwellReply;
                        case 227: return PacketType.ParcelGodMarkAsContent;
                        case 228: return PacketType.ViewerStartAuction;
                        case 235: return PacketType.UUIDNameRequest;
                        case 236: return PacketType.UUIDNameReply;
                        case 237: return PacketType.UUIDGroupNameRequest;
                        case 238: return PacketType.UUIDGroupNameReply;
                        case 240: return PacketType.ChildAgentDying;
                        case 241: return PacketType.ChildAgentUnknown;
                        case 243: return PacketType.GetScriptRunning;
                        case 244: return PacketType.ScriptRunningReply;
                        case 245: return PacketType.SetScriptRunning;
                        case 246: return PacketType.ScriptReset;
                        case 247: return PacketType.ScriptSensorRequest;
                        case 248: return PacketType.ScriptSensorReply;
                        case 249: return PacketType.CompleteAgentMovement;
                        case 250: return PacketType.AgentMovementComplete;
                        case 252: return PacketType.LogoutRequest;
                        case 253: return PacketType.LogoutReply;
                        case 254: return PacketType.ImprovedInstantMessage;
                        case 255: return PacketType.RetrieveInstantMessages;
                        case 256: return PacketType.FindAgent;
                        case 257: return PacketType.RequestGodlikePowers;
                        case 258: return PacketType.GrantGodlikePowers;
                        case 259: return PacketType.GodlikeMessage;
                        case 260: return PacketType.EstateOwnerMessage;
                        case 261: return PacketType.GenericMessage;
                        case 262: return PacketType.MuteListRequest;
                        case 263: return PacketType.UpdateMuteListEntry;
                        case 264: return PacketType.RemoveMuteListEntry;
                        case 265: return PacketType.CopyInventoryFromNotecard;
                        case 266: return PacketType.UpdateInventoryItem;
                        case 267: return PacketType.UpdateCreateInventoryItem;
                        case 268: return PacketType.MoveInventoryItem;
                        case 269: return PacketType.CopyInventoryItem;
                        case 270: return PacketType.RemoveInventoryItem;
                        case 271: return PacketType.ChangeInventoryItemFlags;
                        case 272: return PacketType.SaveAssetIntoInventory;
                        case 273: return PacketType.CreateInventoryFolder;
                        case 274: return PacketType.UpdateInventoryFolder;
                        case 275: return PacketType.MoveInventoryFolder;
                        case 276: return PacketType.RemoveInventoryFolder;
                        case 277: return PacketType.FetchInventoryDescendents;
                        case 278: return PacketType.InventoryDescendents;
                        case 279: return PacketType.FetchInventory;
                        case 280: return PacketType.FetchInventoryReply;
                        case 281: return PacketType.BulkUpdateInventory;
                        case 284: return PacketType.RemoveInventoryObjects;
                        case 285: return PacketType.PurgeInventoryDescendents;
                        case 286: return PacketType.UpdateTaskInventory;
                        case 287: return PacketType.RemoveTaskInventory;
                        case 288: return PacketType.MoveTaskInventory;
                        case 289: return PacketType.RequestTaskInventory;
                        case 290: return PacketType.ReplyTaskInventory;
                        case 291: return PacketType.DeRezObject;
                        case 292: return PacketType.DeRezAck;
                        case 293: return PacketType.RezObject;
                        case 294: return PacketType.RezObjectFromNotecard;
                        case 297: return PacketType.AcceptFriendship;
                        case 298: return PacketType.DeclineFriendship;
                        case 300: return PacketType.TerminateFriendship;
                        case 301: return PacketType.OfferCallingCard;
                        case 302: return PacketType.AcceptCallingCard;
                        case 303: return PacketType.DeclineCallingCard;
                        case 304: return PacketType.RezScript;
                        case 305: return PacketType.CreateInventoryItem;
                        case 306: return PacketType.CreateLandmarkForEvent;
                        case 309: return PacketType.RegionHandleRequest;
                        case 310: return PacketType.RegionIDAndHandleReply;
                        case 311: return PacketType.MoneyTransferRequest;
                        case 313: return PacketType.MoneyBalanceRequest;
                        case 314: return PacketType.MoneyBalanceReply;
                        case 315: return PacketType.RoutedMoneyBalanceReply;
                        case 316: return PacketType.ActivateGestures;
                        case 317: return PacketType.DeactivateGestures;
                        case 318: return PacketType.MuteListUpdate;
                        case 319: return PacketType.UseCachedMuteList;
                        case 320: return PacketType.GrantUserRights;
                        case 321: return PacketType.ChangeUserRights;
                        case 322: return PacketType.OnlineNotification;
                        case 323: return PacketType.OfflineNotification;
                        case 324: return PacketType.SetStartLocationRequest;
                        case 333: return PacketType.AssetUploadRequest;
                        case 334: return PacketType.AssetUploadComplete;
                        case 339: return PacketType.CreateGroupRequest;
                        case 340: return PacketType.CreateGroupReply;
                        case 341: return PacketType.UpdateGroupInfo;
                        case 342: return PacketType.GroupRoleChanges;
                        case 343: return PacketType.JoinGroupRequest;
                        case 344: return PacketType.JoinGroupReply;
                        case 345: return PacketType.EjectGroupMemberRequest;
                        case 346: return PacketType.EjectGroupMemberReply;
                        case 347: return PacketType.LeaveGroupRequest;
                        case 348: return PacketType.LeaveGroupReply;
                        case 349: return PacketType.InviteGroupRequest;
                        case 351: return PacketType.GroupProfileRequest;
                        case 352: return PacketType.GroupProfileReply;
                        case 353: return PacketType.GroupAccountSummaryRequest;
                        case 354: return PacketType.GroupAccountSummaryReply;
                        case 355: return PacketType.GroupAccountDetailsRequest;
                        case 356: return PacketType.GroupAccountDetailsReply;
                        case 357: return PacketType.GroupAccountTransactionsRequest;
                        case 358: return PacketType.GroupAccountTransactionsReply;
                        case 359: return PacketType.GroupActiveProposalsRequest;
                        case 360: return PacketType.GroupActiveProposalItemReply;
                        case 361: return PacketType.GroupVoteHistoryRequest;
                        case 362: return PacketType.GroupVoteHistoryItemReply;
                        case 363: return PacketType.StartGroupProposal;
                        case 364: return PacketType.GroupProposalBallot;
                        case 366: return PacketType.GroupMembersRequest;
                        case 367: return PacketType.GroupMembersReply;
                        case 368: return PacketType.ActivateGroup;
                        case 369: return PacketType.SetGroupContribution;
                        case 370: return PacketType.SetGroupAcceptNotices;
                        case 371: return PacketType.GroupRoleDataRequest;
                        case 372: return PacketType.GroupRoleDataReply;
                        case 373: return PacketType.GroupRoleMembersRequest;
                        case 374: return PacketType.GroupRoleMembersReply;
                        case 375: return PacketType.GroupTitlesRequest;
                        case 376: return PacketType.GroupTitlesReply;
                        case 377: return PacketType.GroupTitleUpdate;
                        case 378: return PacketType.GroupRoleUpdate;
                        case 379: return PacketType.LiveHelpGroupRequest;
                        case 380: return PacketType.LiveHelpGroupReply;
                        case 381: return PacketType.AgentWearablesRequest;
                        case 382: return PacketType.AgentWearablesUpdate;
                        case 383: return PacketType.AgentIsNowWearing;
                        case 384: return PacketType.AgentCachedTexture;
                        case 385: return PacketType.AgentCachedTextureResponse;
                        case 386: return PacketType.AgentDataUpdateRequest;
                        case 387: return PacketType.AgentDataUpdate;
                        case 388: return PacketType.GroupDataUpdate;
                        case 389: return PacketType.AgentGroupDataUpdate;
                        case 390: return PacketType.AgentDropGroup;
                        case 395: return PacketType.RezSingleAttachmentFromInv;
                        case 396: return PacketType.RezMultipleAttachmentsFromInv;
                        case 397: return PacketType.DetachAttachmentIntoInv;
                        case 398: return PacketType.CreateNewOutfitAttachments;
                        case 399: return PacketType.UserInfoRequest;
                        case 400: return PacketType.UserInfoReply;
                        case 401: return PacketType.UpdateUserInfo;
                        case 403: return PacketType.InitiateDownload;
                        case 405: return PacketType.MapLayerRequest;
                        case 406: return PacketType.MapLayerReply;
                        case 407: return PacketType.MapBlockRequest;
                        case 408: return PacketType.MapNameRequest;
                        case 409: return PacketType.MapBlockReply;
                        case 410: return PacketType.MapItemRequest;
                        case 411: return PacketType.MapItemReply;
                        case 412: return PacketType.SendPostcard;
                        case 419: return PacketType.ParcelMediaCommandMessage;
                        case 420: return PacketType.ParcelMediaUpdate;
                        case 421: return PacketType.LandStatRequest;
                        case 422: return PacketType.LandStatReply;
                        case 423: return PacketType.Error;
                        case 424: return PacketType.ObjectIncludeInSearch;
                        case 425: return PacketType.RezRestoreToWorld;
                        case 426: return PacketType.LinkInventoryItem;
                        case 65531: return PacketType.PacketAck;
                        case 65532: return PacketType.OpenCircuit;
                        case 65533: return PacketType.CloseCircuit;
                    }
                    break;
                case PacketFrequency.Medium:
                    switch (id)
                    {
                        case 1: return PacketType.ObjectAdd;
                        case 2: return PacketType.MultipleObjectUpdate;
                        case 3: return PacketType.RequestMultipleObjects;
                        case 4: return PacketType.ObjectPosition;
                        case 5: return PacketType.RequestObjectPropertiesFamily;
                        case 6: return PacketType.CoarseLocationUpdate;
                        case 7: return PacketType.CrossedRegion;
                        case 8: return PacketType.ConfirmEnableSimulator;
                        case 9: return PacketType.ObjectProperties;
                        case 10: return PacketType.ObjectPropertiesFamily;
                        case 11: return PacketType.ParcelPropertiesRequest;
                        case 13: return PacketType.AttachedSound;
                        case 14: return PacketType.AttachedSoundGainChange;
                        case 15: return PacketType.PreloadSound;
                        case 17: return PacketType.ViewerEffect;
                    }
                    break;
                case PacketFrequency.High:
                    switch (id)
                    {
                        case 1: return PacketType.StartPingCheck;
                        case 2: return PacketType.CompletePingCheck;
                        case 4: return PacketType.AgentUpdate;
                        case 5: return PacketType.AgentAnimation;
                        case 6: return PacketType.AgentRequestSit;
                        case 7: return PacketType.AgentSit;
                        case 8: return PacketType.RequestImage;
                        case 9: return PacketType.ImageData;
                        case 10: return PacketType.ImagePacket;
                        case 11: return PacketType.LayerData;
                        case 12: return PacketType.ObjectUpdate;
                        case 13: return PacketType.ObjectUpdateCompressed;
                        case 14: return PacketType.ObjectUpdateCached;
                        case 15: return PacketType.ImprovedTerseObjectUpdate;
                        case 16: return PacketType.KillObject;
                        case 17: return PacketType.TransferPacket;
                        case 18: return PacketType.SendXferPacket;
                        case 19: return PacketType.ConfirmXferPacket;
                        case 20: return PacketType.AvatarAnimation;
                        case 21: return PacketType.AvatarSitResponse;
                        case 22: return PacketType.CameraConstraint;
                        case 23: return PacketType.ParcelProperties;
                        case 25: return PacketType.ChildAgentUpdate;
                        case 26: return PacketType.ChildAgentAlive;
                        case 27: return PacketType.ChildAgentPositionUpdate;
                        case 29: return PacketType.SoundTrigger;
                    }
                    break;
            }

            return PacketType.Default;
        }

        public static Packet BuildPacket(PacketType type)
        {
            if(type == PacketType.StartPingCheck) return new StartPingCheckPacket();
            if(type == PacketType.CompletePingCheck) return new CompletePingCheckPacket();
            if(type == PacketType.AgentUpdate) return new AgentUpdatePacket();
            if(type == PacketType.AgentAnimation) return new AgentAnimationPacket();
            if(type == PacketType.AgentRequestSit) return new AgentRequestSitPacket();
            if(type == PacketType.AgentSit) return new AgentSitPacket();
            if(type == PacketType.RequestImage) return new RequestImagePacket();
            if(type == PacketType.ImageData) return new ImageDataPacket();
            if(type == PacketType.ImagePacket) return new ImagePacketPacket();
            if(type == PacketType.LayerData) return new LayerDataPacket();
            if(type == PacketType.ObjectUpdate) return new ObjectUpdatePacket();
            if(type == PacketType.ObjectUpdateCompressed) return new ObjectUpdateCompressedPacket();
            if(type == PacketType.ObjectUpdateCached) return new ObjectUpdateCachedPacket();
            if(type == PacketType.ImprovedTerseObjectUpdate) return new ImprovedTerseObjectUpdatePacket();
            if(type == PacketType.KillObject) return new KillObjectPacket();
            if(type == PacketType.TransferPacket) return new TransferPacketPacket();
            if(type == PacketType.SendXferPacket) return new SendXferPacketPacket();
            if(type == PacketType.ConfirmXferPacket) return new ConfirmXferPacketPacket();
            if(type == PacketType.AvatarAnimation) return new AvatarAnimationPacket();
            if(type == PacketType.AvatarSitResponse) return new AvatarSitResponsePacket();
            if(type == PacketType.CameraConstraint) return new CameraConstraintPacket();
            if(type == PacketType.ParcelProperties) return new ParcelPropertiesPacket();
            if(type == PacketType.ChildAgentUpdate) return new ChildAgentUpdatePacket();
            if(type == PacketType.ChildAgentAlive) return new ChildAgentAlivePacket();
            if(type == PacketType.ChildAgentPositionUpdate) return new ChildAgentPositionUpdatePacket();
            if(type == PacketType.SoundTrigger) return new SoundTriggerPacket();
            if(type == PacketType.ObjectAdd) return new ObjectAddPacket();
            if(type == PacketType.MultipleObjectUpdate) return new MultipleObjectUpdatePacket();
            if(type == PacketType.RequestMultipleObjects) return new RequestMultipleObjectsPacket();
            if(type == PacketType.ObjectPosition) return new ObjectPositionPacket();
            if(type == PacketType.RequestObjectPropertiesFamily) return new RequestObjectPropertiesFamilyPacket();
            if(type == PacketType.CoarseLocationUpdate) return new CoarseLocationUpdatePacket();
            if(type == PacketType.CrossedRegion) return new CrossedRegionPacket();
            if(type == PacketType.ConfirmEnableSimulator) return new ConfirmEnableSimulatorPacket();
            if(type == PacketType.ObjectProperties) return new ObjectPropertiesPacket();
            if(type == PacketType.ObjectPropertiesFamily) return new ObjectPropertiesFamilyPacket();
            if(type == PacketType.ParcelPropertiesRequest) return new ParcelPropertiesRequestPacket();
            if(type == PacketType.AttachedSound) return new AttachedSoundPacket();
            if(type == PacketType.AttachedSoundGainChange) return new AttachedSoundGainChangePacket();
            if(type == PacketType.PreloadSound) return new PreloadSoundPacket();
            if(type == PacketType.ViewerEffect) return new ViewerEffectPacket();
            if(type == PacketType.TestMessage) return new TestMessagePacket();
            if(type == PacketType.UseCircuitCode) return new UseCircuitCodePacket();
            if(type == PacketType.TelehubInfo) return new TelehubInfoPacket();
            if(type == PacketType.EconomyDataRequest) return new EconomyDataRequestPacket();
            if(type == PacketType.EconomyData) return new EconomyDataPacket();
            if(type == PacketType.AvatarPickerRequest) return new AvatarPickerRequestPacket();
            if(type == PacketType.AvatarPickerReply) return new AvatarPickerReplyPacket();
            if(type == PacketType.PlacesQuery) return new PlacesQueryPacket();
            if(type == PacketType.PlacesReply) return new PlacesReplyPacket();
            if(type == PacketType.DirFindQuery) return new DirFindQueryPacket();
            if(type == PacketType.DirPlacesQuery) return new DirPlacesQueryPacket();
            if(type == PacketType.DirPlacesReply) return new DirPlacesReplyPacket();
            if(type == PacketType.DirPeopleReply) return new DirPeopleReplyPacket();
            if(type == PacketType.DirEventsReply) return new DirEventsReplyPacket();
            if(type == PacketType.DirGroupsReply) return new DirGroupsReplyPacket();
            if(type == PacketType.DirClassifiedQuery) return new DirClassifiedQueryPacket();
            if(type == PacketType.DirClassifiedReply) return new DirClassifiedReplyPacket();
            if(type == PacketType.AvatarClassifiedReply) return new AvatarClassifiedReplyPacket();
            if(type == PacketType.ClassifiedInfoRequest) return new ClassifiedInfoRequestPacket();
            if(type == PacketType.ClassifiedInfoReply) return new ClassifiedInfoReplyPacket();
            if(type == PacketType.ClassifiedInfoUpdate) return new ClassifiedInfoUpdatePacket();
            if(type == PacketType.ClassifiedDelete) return new ClassifiedDeletePacket();
            if(type == PacketType.ClassifiedGodDelete) return new ClassifiedGodDeletePacket();
            if(type == PacketType.DirLandQuery) return new DirLandQueryPacket();
            if(type == PacketType.DirLandReply) return new DirLandReplyPacket();
            if(type == PacketType.DirPopularQuery) return new DirPopularQueryPacket();
            if(type == PacketType.DirPopularReply) return new DirPopularReplyPacket();
            if(type == PacketType.ParcelInfoRequest) return new ParcelInfoRequestPacket();
            if(type == PacketType.ParcelInfoReply) return new ParcelInfoReplyPacket();
            if(type == PacketType.ParcelObjectOwnersRequest) return new ParcelObjectOwnersRequestPacket();
            if(type == PacketType.ParcelObjectOwnersReply) return new ParcelObjectOwnersReplyPacket();
            if(type == PacketType.GroupNoticesListRequest) return new GroupNoticesListRequestPacket();
            if(type == PacketType.GroupNoticesListReply) return new GroupNoticesListReplyPacket();
            if(type == PacketType.GroupNoticeRequest) return new GroupNoticeRequestPacket();
            if(type == PacketType.TeleportRequest) return new TeleportRequestPacket();
            if(type == PacketType.TeleportLocationRequest) return new TeleportLocationRequestPacket();
            if(type == PacketType.TeleportLocal) return new TeleportLocalPacket();
            if(type == PacketType.TeleportLandmarkRequest) return new TeleportLandmarkRequestPacket();
            if(type == PacketType.TeleportProgress) return new TeleportProgressPacket();
            if(type == PacketType.TeleportFinish) return new TeleportFinishPacket();
            if(type == PacketType.StartLure) return new StartLurePacket();
            if(type == PacketType.TeleportLureRequest) return new TeleportLureRequestPacket();
            if(type == PacketType.TeleportCancel) return new TeleportCancelPacket();
            if(type == PacketType.TeleportStart) return new TeleportStartPacket();
            if(type == PacketType.TeleportFailed) return new TeleportFailedPacket();
            if(type == PacketType.Undo) return new UndoPacket();
            if(type == PacketType.Redo) return new RedoPacket();
            if(type == PacketType.UndoLand) return new UndoLandPacket();
            if(type == PacketType.AgentPause) return new AgentPausePacket();
            if(type == PacketType.AgentResume) return new AgentResumePacket();
            if(type == PacketType.ChatFromViewer) return new ChatFromViewerPacket();
            if(type == PacketType.AgentThrottle) return new AgentThrottlePacket();
            if(type == PacketType.AgentFOV) return new AgentFOVPacket();
            if(type == PacketType.AgentHeightWidth) return new AgentHeightWidthPacket();
            if(type == PacketType.AgentSetAppearance) return new AgentSetAppearancePacket();
            if(type == PacketType.AgentQuitCopy) return new AgentQuitCopyPacket();
            if(type == PacketType.ImageNotInDatabase) return new ImageNotInDatabasePacket();
            if(type == PacketType.RebakeAvatarTextures) return new RebakeAvatarTexturesPacket();
            if(type == PacketType.SetAlwaysRun) return new SetAlwaysRunPacket();
            if(type == PacketType.ObjectDelete) return new ObjectDeletePacket();
            if(type == PacketType.ObjectDuplicate) return new ObjectDuplicatePacket();
            if(type == PacketType.ObjectDuplicateOnRay) return new ObjectDuplicateOnRayPacket();
            if(type == PacketType.ObjectScale) return new ObjectScalePacket();
            if(type == PacketType.ObjectRotation) return new ObjectRotationPacket();
            if(type == PacketType.ObjectFlagUpdate) return new ObjectFlagUpdatePacket();
            if(type == PacketType.ObjectClickAction) return new ObjectClickActionPacket();
            if(type == PacketType.ObjectImage) return new ObjectImagePacket();
            if(type == PacketType.ObjectMaterial) return new ObjectMaterialPacket();
            if(type == PacketType.ObjectShape) return new ObjectShapePacket();
            if(type == PacketType.ObjectExtraParams) return new ObjectExtraParamsPacket();
            if(type == PacketType.ObjectOwner) return new ObjectOwnerPacket();
            if(type == PacketType.ObjectGroup) return new ObjectGroupPacket();
            if(type == PacketType.ObjectBuy) return new ObjectBuyPacket();
            if(type == PacketType.BuyObjectInventory) return new BuyObjectInventoryPacket();
            if(type == PacketType.DerezContainer) return new DerezContainerPacket();
            if(type == PacketType.ObjectPermissions) return new ObjectPermissionsPacket();
            if(type == PacketType.ObjectSaleInfo) return new ObjectSaleInfoPacket();
            if(type == PacketType.ObjectName) return new ObjectNamePacket();
            if(type == PacketType.ObjectDescription) return new ObjectDescriptionPacket();
            if(type == PacketType.ObjectCategory) return new ObjectCategoryPacket();
            if(type == PacketType.ObjectSelect) return new ObjectSelectPacket();
            if(type == PacketType.ObjectDeselect) return new ObjectDeselectPacket();
            if(type == PacketType.ObjectAttach) return new ObjectAttachPacket();
            if(type == PacketType.ObjectDetach) return new ObjectDetachPacket();
            if(type == PacketType.ObjectDrop) return new ObjectDropPacket();
            if(type == PacketType.ObjectLink) return new ObjectLinkPacket();
            if(type == PacketType.ObjectDelink) return new ObjectDelinkPacket();
            if(type == PacketType.ObjectGrab) return new ObjectGrabPacket();
            if(type == PacketType.ObjectGrabUpdate) return new ObjectGrabUpdatePacket();
            if(type == PacketType.ObjectDeGrab) return new ObjectDeGrabPacket();
            if(type == PacketType.ObjectSpinStart) return new ObjectSpinStartPacket();
            if(type == PacketType.ObjectSpinUpdate) return new ObjectSpinUpdatePacket();
            if(type == PacketType.ObjectSpinStop) return new ObjectSpinStopPacket();
            if(type == PacketType.ObjectExportSelected) return new ObjectExportSelectedPacket();
            if(type == PacketType.ModifyLand) return new ModifyLandPacket();
            if(type == PacketType.VelocityInterpolateOn) return new VelocityInterpolateOnPacket();
            if(type == PacketType.VelocityInterpolateOff) return new VelocityInterpolateOffPacket();
            if(type == PacketType.StateSave) return new StateSavePacket();
            if(type == PacketType.ReportAutosaveCrash) return new ReportAutosaveCrashPacket();
            if(type == PacketType.SimWideDeletes) return new SimWideDeletesPacket();
            if(type == PacketType.TrackAgent) return new TrackAgentPacket();
            if(type == PacketType.ViewerStats) return new ViewerStatsPacket();
            if(type == PacketType.ScriptAnswerYes) return new ScriptAnswerYesPacket();
            if(type == PacketType.UserReport) return new UserReportPacket();
            if(type == PacketType.AlertMessage) return new AlertMessagePacket();
            if(type == PacketType.AgentAlertMessage) return new AgentAlertMessagePacket();
            if(type == PacketType.MeanCollisionAlert) return new MeanCollisionAlertPacket();
            if(type == PacketType.ViewerFrozenMessage) return new ViewerFrozenMessagePacket();
            if(type == PacketType.HealthMessage) return new HealthMessagePacket();
            if(type == PacketType.ChatFromSimulator) return new ChatFromSimulatorPacket();
            if(type == PacketType.SimStats) return new SimStatsPacket();
            if(type == PacketType.RequestRegionInfo) return new RequestRegionInfoPacket();
            if(type == PacketType.RegionInfo) return new RegionInfoPacket();
            if(type == PacketType.GodUpdateRegionInfo) return new GodUpdateRegionInfoPacket();
            if(type == PacketType.RegionHandshake) return new RegionHandshakePacket();
            if(type == PacketType.RegionHandshakeReply) return new RegionHandshakeReplyPacket();
            if(type == PacketType.SimulatorViewerTimeMessage) return new SimulatorViewerTimeMessagePacket();
            if(type == PacketType.EnableSimulator) return new EnableSimulatorPacket();
            if(type == PacketType.DisableSimulator) return new DisableSimulatorPacket();
            if(type == PacketType.TransferRequest) return new TransferRequestPacket();
            if(type == PacketType.TransferInfo) return new TransferInfoPacket();
            if(type == PacketType.TransferAbort) return new TransferAbortPacket();
            if(type == PacketType.RequestXfer) return new RequestXferPacket();
            if(type == PacketType.AbortXfer) return new AbortXferPacket();
            if(type == PacketType.AvatarAppearance) return new AvatarAppearancePacket();
            if(type == PacketType.SetFollowCamProperties) return new SetFollowCamPropertiesPacket();
            if(type == PacketType.ClearFollowCamProperties) return new ClearFollowCamPropertiesPacket();
            if(type == PacketType.RequestPayPrice) return new RequestPayPricePacket();
            if(type == PacketType.PayPriceReply) return new PayPriceReplyPacket();
            if(type == PacketType.KickUser) return new KickUserPacket();
            if(type == PacketType.GodKickUser) return new GodKickUserPacket();
            if(type == PacketType.EjectUser) return new EjectUserPacket();
            if(type == PacketType.FreezeUser) return new FreezeUserPacket();
            if(type == PacketType.AvatarPropertiesRequest) return new AvatarPropertiesRequestPacket();
            if(type == PacketType.AvatarPropertiesReply) return new AvatarPropertiesReplyPacket();
            if(type == PacketType.AvatarInterestsReply) return new AvatarInterestsReplyPacket();
            if(type == PacketType.AvatarGroupsReply) return new AvatarGroupsReplyPacket();
            if(type == PacketType.AvatarPropertiesUpdate) return new AvatarPropertiesUpdatePacket();
            if(type == PacketType.AvatarInterestsUpdate) return new AvatarInterestsUpdatePacket();
            if(type == PacketType.AvatarNotesReply) return new AvatarNotesReplyPacket();
            if(type == PacketType.AvatarNotesUpdate) return new AvatarNotesUpdatePacket();
            if(type == PacketType.AvatarPicksReply) return new AvatarPicksReplyPacket();
            if(type == PacketType.EventInfoRequest) return new EventInfoRequestPacket();
            if(type == PacketType.EventInfoReply) return new EventInfoReplyPacket();
            if(type == PacketType.EventNotificationAddRequest) return new EventNotificationAddRequestPacket();
            if(type == PacketType.EventNotificationRemoveRequest) return new EventNotificationRemoveRequestPacket();
            if(type == PacketType.EventGodDelete) return new EventGodDeletePacket();
            if(type == PacketType.PickInfoReply) return new PickInfoReplyPacket();
            if(type == PacketType.PickInfoUpdate) return new PickInfoUpdatePacket();
            if(type == PacketType.PickDelete) return new PickDeletePacket();
            if(type == PacketType.PickGodDelete) return new PickGodDeletePacket();
            if(type == PacketType.ScriptQuestion) return new ScriptQuestionPacket();
            if(type == PacketType.ScriptControlChange) return new ScriptControlChangePacket();
            if(type == PacketType.ScriptDialog) return new ScriptDialogPacket();
            if(type == PacketType.ScriptDialogReply) return new ScriptDialogReplyPacket();
            if(type == PacketType.ForceScriptControlRelease) return new ForceScriptControlReleasePacket();
            if(type == PacketType.RevokePermissions) return new RevokePermissionsPacket();
            if(type == PacketType.LoadURL) return new LoadURLPacket();
            if(type == PacketType.ScriptTeleportRequest) return new ScriptTeleportRequestPacket();
            if(type == PacketType.ParcelOverlay) return new ParcelOverlayPacket();
            if(type == PacketType.ParcelPropertiesRequestByID) return new ParcelPropertiesRequestByIDPacket();
            if(type == PacketType.ParcelPropertiesUpdate) return new ParcelPropertiesUpdatePacket();
            if(type == PacketType.ParcelReturnObjects) return new ParcelReturnObjectsPacket();
            if(type == PacketType.ParcelSetOtherCleanTime) return new ParcelSetOtherCleanTimePacket();
            if(type == PacketType.ParcelDisableObjects) return new ParcelDisableObjectsPacket();
            if(type == PacketType.ParcelSelectObjects) return new ParcelSelectObjectsPacket();
            if(type == PacketType.EstateCovenantRequest) return new EstateCovenantRequestPacket();
            if(type == PacketType.EstateCovenantReply) return new EstateCovenantReplyPacket();
            if(type == PacketType.ForceObjectSelect) return new ForceObjectSelectPacket();
            if(type == PacketType.ParcelBuyPass) return new ParcelBuyPassPacket();
            if(type == PacketType.ParcelDeedToGroup) return new ParcelDeedToGroupPacket();
            if(type == PacketType.ParcelReclaim) return new ParcelReclaimPacket();
            if(type == PacketType.ParcelClaim) return new ParcelClaimPacket();
            if(type == PacketType.ParcelJoin) return new ParcelJoinPacket();
            if(type == PacketType.ParcelDivide) return new ParcelDividePacket();
            if(type == PacketType.ParcelRelease) return new ParcelReleasePacket();
            if(type == PacketType.ParcelBuy) return new ParcelBuyPacket();
            if(type == PacketType.ParcelGodForceOwner) return new ParcelGodForceOwnerPacket();
            if(type == PacketType.ParcelAccessListRequest) return new ParcelAccessListRequestPacket();
            if(type == PacketType.ParcelAccessListReply) return new ParcelAccessListReplyPacket();
            if(type == PacketType.ParcelAccessListUpdate) return new ParcelAccessListUpdatePacket();
            if(type == PacketType.ParcelDwellRequest) return new ParcelDwellRequestPacket();
            if(type == PacketType.ParcelDwellReply) return new ParcelDwellReplyPacket();
            if(type == PacketType.ParcelGodMarkAsContent) return new ParcelGodMarkAsContentPacket();
            if(type == PacketType.ViewerStartAuction) return new ViewerStartAuctionPacket();
            if(type == PacketType.UUIDNameRequest) return new UUIDNameRequestPacket();
            if(type == PacketType.UUIDNameReply) return new UUIDNameReplyPacket();
            if(type == PacketType.UUIDGroupNameRequest) return new UUIDGroupNameRequestPacket();
            if(type == PacketType.UUIDGroupNameReply) return new UUIDGroupNameReplyPacket();
            if(type == PacketType.ChildAgentDying) return new ChildAgentDyingPacket();
            if(type == PacketType.ChildAgentUnknown) return new ChildAgentUnknownPacket();
            if(type == PacketType.GetScriptRunning) return new GetScriptRunningPacket();
            if(type == PacketType.ScriptRunningReply) return new ScriptRunningReplyPacket();
            if(type == PacketType.SetScriptRunning) return new SetScriptRunningPacket();
            if(type == PacketType.ScriptReset) return new ScriptResetPacket();
            if(type == PacketType.ScriptSensorRequest) return new ScriptSensorRequestPacket();
            if(type == PacketType.ScriptSensorReply) return new ScriptSensorReplyPacket();
            if(type == PacketType.CompleteAgentMovement) return new CompleteAgentMovementPacket();
            if(type == PacketType.AgentMovementComplete) return new AgentMovementCompletePacket();
            if(type == PacketType.LogoutRequest) return new LogoutRequestPacket();
            if(type == PacketType.LogoutReply) return new LogoutReplyPacket();
            if(type == PacketType.ImprovedInstantMessage) return new ImprovedInstantMessagePacket();
            if(type == PacketType.RetrieveInstantMessages) return new RetrieveInstantMessagesPacket();
            if(type == PacketType.FindAgent) return new FindAgentPacket();
            if(type == PacketType.RequestGodlikePowers) return new RequestGodlikePowersPacket();
            if(type == PacketType.GrantGodlikePowers) return new GrantGodlikePowersPacket();
            if(type == PacketType.GodlikeMessage) return new GodlikeMessagePacket();
            if(type == PacketType.EstateOwnerMessage) return new EstateOwnerMessagePacket();
            if(type == PacketType.GenericMessage) return new GenericMessagePacket();
            if(type == PacketType.MuteListRequest) return new MuteListRequestPacket();
            if(type == PacketType.UpdateMuteListEntry) return new UpdateMuteListEntryPacket();
            if(type == PacketType.RemoveMuteListEntry) return new RemoveMuteListEntryPacket();
            if(type == PacketType.CopyInventoryFromNotecard) return new CopyInventoryFromNotecardPacket();
            if(type == PacketType.UpdateInventoryItem) return new UpdateInventoryItemPacket();
            if(type == PacketType.UpdateCreateInventoryItem) return new UpdateCreateInventoryItemPacket();
            if(type == PacketType.MoveInventoryItem) return new MoveInventoryItemPacket();
            if(type == PacketType.CopyInventoryItem) return new CopyInventoryItemPacket();
            if(type == PacketType.RemoveInventoryItem) return new RemoveInventoryItemPacket();
            if(type == PacketType.ChangeInventoryItemFlags) return new ChangeInventoryItemFlagsPacket();
            if(type == PacketType.SaveAssetIntoInventory) return new SaveAssetIntoInventoryPacket();
            if(type == PacketType.CreateInventoryFolder) return new CreateInventoryFolderPacket();
            if(type == PacketType.UpdateInventoryFolder) return new UpdateInventoryFolderPacket();
            if(type == PacketType.MoveInventoryFolder) return new MoveInventoryFolderPacket();
            if(type == PacketType.RemoveInventoryFolder) return new RemoveInventoryFolderPacket();
            if(type == PacketType.FetchInventoryDescendents) return new FetchInventoryDescendentsPacket();
            if(type == PacketType.InventoryDescendents) return new InventoryDescendentsPacket();
            if(type == PacketType.FetchInventory) return new FetchInventoryPacket();
            if(type == PacketType.FetchInventoryReply) return new FetchInventoryReplyPacket();
            if(type == PacketType.BulkUpdateInventory) return new BulkUpdateInventoryPacket();
            if(type == PacketType.RemoveInventoryObjects) return new RemoveInventoryObjectsPacket();
            if(type == PacketType.PurgeInventoryDescendents) return new PurgeInventoryDescendentsPacket();
            if(type == PacketType.UpdateTaskInventory) return new UpdateTaskInventoryPacket();
            if(type == PacketType.RemoveTaskInventory) return new RemoveTaskInventoryPacket();
            if(type == PacketType.MoveTaskInventory) return new MoveTaskInventoryPacket();
            if(type == PacketType.RequestTaskInventory) return new RequestTaskInventoryPacket();
            if(type == PacketType.ReplyTaskInventory) return new ReplyTaskInventoryPacket();
            if(type == PacketType.DeRezObject) return new DeRezObjectPacket();
            if(type == PacketType.DeRezAck) return new DeRezAckPacket();
            if(type == PacketType.RezObject) return new RezObjectPacket();
            if(type == PacketType.RezObjectFromNotecard) return new RezObjectFromNotecardPacket();
            if(type == PacketType.AcceptFriendship) return new AcceptFriendshipPacket();
            if(type == PacketType.DeclineFriendship) return new DeclineFriendshipPacket();
            if(type == PacketType.TerminateFriendship) return new TerminateFriendshipPacket();
            if(type == PacketType.OfferCallingCard) return new OfferCallingCardPacket();
            if(type == PacketType.AcceptCallingCard) return new AcceptCallingCardPacket();
            if(type == PacketType.DeclineCallingCard) return new DeclineCallingCardPacket();
            if(type == PacketType.RezScript) return new RezScriptPacket();
            if(type == PacketType.CreateInventoryItem) return new CreateInventoryItemPacket();
            if(type == PacketType.CreateLandmarkForEvent) return new CreateLandmarkForEventPacket();
            if(type == PacketType.RegionHandleRequest) return new RegionHandleRequestPacket();
            if(type == PacketType.RegionIDAndHandleReply) return new RegionIDAndHandleReplyPacket();
            if(type == PacketType.MoneyTransferRequest) return new MoneyTransferRequestPacket();
            if(type == PacketType.MoneyBalanceRequest) return new MoneyBalanceRequestPacket();
            if(type == PacketType.MoneyBalanceReply) return new MoneyBalanceReplyPacket();
            if(type == PacketType.RoutedMoneyBalanceReply) return new RoutedMoneyBalanceReplyPacket();
            if(type == PacketType.ActivateGestures) return new ActivateGesturesPacket();
            if(type == PacketType.DeactivateGestures) return new DeactivateGesturesPacket();
            if(type == PacketType.MuteListUpdate) return new MuteListUpdatePacket();
            if(type == PacketType.UseCachedMuteList) return new UseCachedMuteListPacket();
            if(type == PacketType.GrantUserRights) return new GrantUserRightsPacket();
            if(type == PacketType.ChangeUserRights) return new ChangeUserRightsPacket();
            if(type == PacketType.OnlineNotification) return new OnlineNotificationPacket();
            if(type == PacketType.OfflineNotification) return new OfflineNotificationPacket();
            if(type == PacketType.SetStartLocationRequest) return new SetStartLocationRequestPacket();
            if(type == PacketType.AssetUploadRequest) return new AssetUploadRequestPacket();
            if(type == PacketType.AssetUploadComplete) return new AssetUploadCompletePacket();
            if(type == PacketType.CreateGroupRequest) return new CreateGroupRequestPacket();
            if(type == PacketType.CreateGroupReply) return new CreateGroupReplyPacket();
            if(type == PacketType.UpdateGroupInfo) return new UpdateGroupInfoPacket();
            if(type == PacketType.GroupRoleChanges) return new GroupRoleChangesPacket();
            if(type == PacketType.JoinGroupRequest) return new JoinGroupRequestPacket();
            if(type == PacketType.JoinGroupReply) return new JoinGroupReplyPacket();
            if(type == PacketType.EjectGroupMemberRequest) return new EjectGroupMemberRequestPacket();
            if(type == PacketType.EjectGroupMemberReply) return new EjectGroupMemberReplyPacket();
            if(type == PacketType.LeaveGroupRequest) return new LeaveGroupRequestPacket();
            if(type == PacketType.LeaveGroupReply) return new LeaveGroupReplyPacket();
            if(type == PacketType.InviteGroupRequest) return new InviteGroupRequestPacket();
            if(type == PacketType.GroupProfileRequest) return new GroupProfileRequestPacket();
            if(type == PacketType.GroupProfileReply) return new GroupProfileReplyPacket();
            if(type == PacketType.GroupAccountSummaryRequest) return new GroupAccountSummaryRequestPacket();
            if(type == PacketType.GroupAccountSummaryReply) return new GroupAccountSummaryReplyPacket();
            if(type == PacketType.GroupAccountDetailsRequest) return new GroupAccountDetailsRequestPacket();
            if(type == PacketType.GroupAccountDetailsReply) return new GroupAccountDetailsReplyPacket();
            if(type == PacketType.GroupAccountTransactionsRequest) return new GroupAccountTransactionsRequestPacket();
            if(type == PacketType.GroupAccountTransactionsReply) return new GroupAccountTransactionsReplyPacket();
            if(type == PacketType.GroupActiveProposalsRequest) return new GroupActiveProposalsRequestPacket();
            if(type == PacketType.GroupActiveProposalItemReply) return new GroupActiveProposalItemReplyPacket();
            if(type == PacketType.GroupVoteHistoryRequest) return new GroupVoteHistoryRequestPacket();
            if(type == PacketType.GroupVoteHistoryItemReply) return new GroupVoteHistoryItemReplyPacket();
            if(type == PacketType.StartGroupProposal) return new StartGroupProposalPacket();
            if(type == PacketType.GroupProposalBallot) return new GroupProposalBallotPacket();
            if(type == PacketType.GroupMembersRequest) return new GroupMembersRequestPacket();
            if(type == PacketType.GroupMembersReply) return new GroupMembersReplyPacket();
            if(type == PacketType.ActivateGroup) return new ActivateGroupPacket();
            if(type == PacketType.SetGroupContribution) return new SetGroupContributionPacket();
            if(type == PacketType.SetGroupAcceptNotices) return new SetGroupAcceptNoticesPacket();
            if(type == PacketType.GroupRoleDataRequest) return new GroupRoleDataRequestPacket();
            if(type == PacketType.GroupRoleDataReply) return new GroupRoleDataReplyPacket();
            if(type == PacketType.GroupRoleMembersRequest) return new GroupRoleMembersRequestPacket();
            if(type == PacketType.GroupRoleMembersReply) return new GroupRoleMembersReplyPacket();
            if(type == PacketType.GroupTitlesRequest) return new GroupTitlesRequestPacket();
            if(type == PacketType.GroupTitlesReply) return new GroupTitlesReplyPacket();
            if(type == PacketType.GroupTitleUpdate) return new GroupTitleUpdatePacket();
            if(type == PacketType.GroupRoleUpdate) return new GroupRoleUpdatePacket();
            if(type == PacketType.LiveHelpGroupRequest) return new LiveHelpGroupRequestPacket();
            if(type == PacketType.LiveHelpGroupReply) return new LiveHelpGroupReplyPacket();
            if(type == PacketType.AgentWearablesRequest) return new AgentWearablesRequestPacket();
            if(type == PacketType.AgentWearablesUpdate) return new AgentWearablesUpdatePacket();
            if(type == PacketType.AgentIsNowWearing) return new AgentIsNowWearingPacket();
            if(type == PacketType.AgentCachedTexture) return new AgentCachedTexturePacket();
            if(type == PacketType.AgentCachedTextureResponse) return new AgentCachedTextureResponsePacket();
            if(type == PacketType.AgentDataUpdateRequest) return new AgentDataUpdateRequestPacket();
            if(type == PacketType.AgentDataUpdate) return new AgentDataUpdatePacket();
            if(type == PacketType.GroupDataUpdate) return new GroupDataUpdatePacket();
            if(type == PacketType.AgentGroupDataUpdate) return new AgentGroupDataUpdatePacket();
            if(type == PacketType.AgentDropGroup) return new AgentDropGroupPacket();
            if(type == PacketType.RezSingleAttachmentFromInv) return new RezSingleAttachmentFromInvPacket();
            if(type == PacketType.RezMultipleAttachmentsFromInv) return new RezMultipleAttachmentsFromInvPacket();
            if(type == PacketType.DetachAttachmentIntoInv) return new DetachAttachmentIntoInvPacket();
            if(type == PacketType.CreateNewOutfitAttachments) return new CreateNewOutfitAttachmentsPacket();
            if(type == PacketType.UserInfoRequest) return new UserInfoRequestPacket();
            if(type == PacketType.UserInfoReply) return new UserInfoReplyPacket();
            if(type == PacketType.UpdateUserInfo) return new UpdateUserInfoPacket();
            if(type == PacketType.InitiateDownload) return new InitiateDownloadPacket();
            if(type == PacketType.MapLayerRequest) return new MapLayerRequestPacket();
            if(type == PacketType.MapLayerReply) return new MapLayerReplyPacket();
            if(type == PacketType.MapBlockRequest) return new MapBlockRequestPacket();
            if(type == PacketType.MapNameRequest) return new MapNameRequestPacket();
            if(type == PacketType.MapBlockReply) return new MapBlockReplyPacket();
            if(type == PacketType.MapItemRequest) return new MapItemRequestPacket();
            if(type == PacketType.MapItemReply) return new MapItemReplyPacket();
            if(type == PacketType.SendPostcard) return new SendPostcardPacket();
            if(type == PacketType.ParcelMediaCommandMessage) return new ParcelMediaCommandMessagePacket();
            if(type == PacketType.ParcelMediaUpdate) return new ParcelMediaUpdatePacket();
            if(type == PacketType.LandStatRequest) return new LandStatRequestPacket();
            if(type == PacketType.LandStatReply) return new LandStatReplyPacket();
            if(type == PacketType.Error) return new ErrorPacket();
            if(type == PacketType.ObjectIncludeInSearch) return new ObjectIncludeInSearchPacket();
            if(type == PacketType.RezRestoreToWorld) return new RezRestoreToWorldPacket();
            if(type == PacketType.LinkInventoryItem) return new LinkInventoryItemPacket();
            if(type == PacketType.PacketAck) return new PacketAckPacket();
            if(type == PacketType.OpenCircuit) return new OpenCircuitPacket();
            if(type == PacketType.CloseCircuit) return new CloseCircuitPacket();
            return null;

        }

        public static Packet BuildPacket(byte[] packetBuffer, ref int packetEnd, byte[] zeroBuffer)
        {
            byte[] bytes;
            int i = 0;
            Header header = Header.BuildHeader(packetBuffer, ref i, ref packetEnd);
            if (header.Zerocoded)
            {
                packetEnd = Helpers.ZeroDecode(packetBuffer, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            else
            {
                bytes = packetBuffer;
            }
            Array.Clear(bytes, packetEnd + 1, bytes.Length - packetEnd - 1);

            switch (header.Frequency)
            {
                case PacketFrequency.Low:
                    switch (header.ID)
                    {
                        case 1: return new TestMessagePacket(header, bytes, ref i);
                        case 3: return new UseCircuitCodePacket(header, bytes, ref i);
                        case 10: return new TelehubInfoPacket(header, bytes, ref i);
                        case 24: return new EconomyDataRequestPacket(header, bytes, ref i);
                        case 25: return new EconomyDataPacket(header, bytes, ref i);
                        case 26: return new AvatarPickerRequestPacket(header, bytes, ref i);
                        case 28: return new AvatarPickerReplyPacket(header, bytes, ref i);
                        case 29: return new PlacesQueryPacket(header, bytes, ref i);
                        case 30: return new PlacesReplyPacket(header, bytes, ref i);
                        case 31: return new DirFindQueryPacket(header, bytes, ref i);
                        case 33: return new DirPlacesQueryPacket(header, bytes, ref i);
                        case 35: return new DirPlacesReplyPacket(header, bytes, ref i);
                        case 36: return new DirPeopleReplyPacket(header, bytes, ref i);
                        case 37: return new DirEventsReplyPacket(header, bytes, ref i);
                        case 38: return new DirGroupsReplyPacket(header, bytes, ref i);
                        case 39: return new DirClassifiedQueryPacket(header, bytes, ref i);
                        case 41: return new DirClassifiedReplyPacket(header, bytes, ref i);
                        case 42: return new AvatarClassifiedReplyPacket(header, bytes, ref i);
                        case 43: return new ClassifiedInfoRequestPacket(header, bytes, ref i);
                        case 44: return new ClassifiedInfoReplyPacket(header, bytes, ref i);
                        case 45: return new ClassifiedInfoUpdatePacket(header, bytes, ref i);
                        case 46: return new ClassifiedDeletePacket(header, bytes, ref i);
                        case 47: return new ClassifiedGodDeletePacket(header, bytes, ref i);
                        case 48: return new DirLandQueryPacket(header, bytes, ref i);
                        case 50: return new DirLandReplyPacket(header, bytes, ref i);
                        case 51: return new DirPopularQueryPacket(header, bytes, ref i);
                        case 53: return new DirPopularReplyPacket(header, bytes, ref i);
                        case 54: return new ParcelInfoRequestPacket(header, bytes, ref i);
                        case 55: return new ParcelInfoReplyPacket(header, bytes, ref i);
                        case 56: return new ParcelObjectOwnersRequestPacket(header, bytes, ref i);
                        case 57: return new ParcelObjectOwnersReplyPacket(header, bytes, ref i);
                        case 58: return new GroupNoticesListRequestPacket(header, bytes, ref i);
                        case 59: return new GroupNoticesListReplyPacket(header, bytes, ref i);
                        case 60: return new GroupNoticeRequestPacket(header, bytes, ref i);
                        case 62: return new TeleportRequestPacket(header, bytes, ref i);
                        case 63: return new TeleportLocationRequestPacket(header, bytes, ref i);
                        case 64: return new TeleportLocalPacket(header, bytes, ref i);
                        case 65: return new TeleportLandmarkRequestPacket(header, bytes, ref i);
                        case 66: return new TeleportProgressPacket(header, bytes, ref i);
                        case 69: return new TeleportFinishPacket(header, bytes, ref i);
                        case 70: return new StartLurePacket(header, bytes, ref i);
                        case 71: return new TeleportLureRequestPacket(header, bytes, ref i);
                        case 72: return new TeleportCancelPacket(header, bytes, ref i);
                        case 73: return new TeleportStartPacket(header, bytes, ref i);
                        case 74: return new TeleportFailedPacket(header, bytes, ref i);
                        case 75: return new UndoPacket(header, bytes, ref i);
                        case 76: return new RedoPacket(header, bytes, ref i);
                        case 77: return new UndoLandPacket(header, bytes, ref i);
                        case 78: return new AgentPausePacket(header, bytes, ref i);
                        case 79: return new AgentResumePacket(header, bytes, ref i);
                        case 80: return new ChatFromViewerPacket(header, bytes, ref i);
                        case 81: return new AgentThrottlePacket(header, bytes, ref i);
                        case 82: return new AgentFOVPacket(header, bytes, ref i);
                        case 83: return new AgentHeightWidthPacket(header, bytes, ref i);
                        case 84: return new AgentSetAppearancePacket(header, bytes, ref i);
                        case 85: return new AgentQuitCopyPacket(header, bytes, ref i);
                        case 86: return new ImageNotInDatabasePacket(header, bytes, ref i);
                        case 87: return new RebakeAvatarTexturesPacket(header, bytes, ref i);
                        case 88: return new SetAlwaysRunPacket(header, bytes, ref i);
                        case 89: return new ObjectDeletePacket(header, bytes, ref i);
                        case 90: return new ObjectDuplicatePacket(header, bytes, ref i);
                        case 91: return new ObjectDuplicateOnRayPacket(header, bytes, ref i);
                        case 92: return new ObjectScalePacket(header, bytes, ref i);
                        case 93: return new ObjectRotationPacket(header, bytes, ref i);
                        case 94: return new ObjectFlagUpdatePacket(header, bytes, ref i);
                        case 95: return new ObjectClickActionPacket(header, bytes, ref i);
                        case 96: return new ObjectImagePacket(header, bytes, ref i);
                        case 97: return new ObjectMaterialPacket(header, bytes, ref i);
                        case 98: return new ObjectShapePacket(header, bytes, ref i);
                        case 99: return new ObjectExtraParamsPacket(header, bytes, ref i);
                        case 100: return new ObjectOwnerPacket(header, bytes, ref i);
                        case 101: return new ObjectGroupPacket(header, bytes, ref i);
                        case 102: return new ObjectBuyPacket(header, bytes, ref i);
                        case 103: return new BuyObjectInventoryPacket(header, bytes, ref i);
                        case 104: return new DerezContainerPacket(header, bytes, ref i);
                        case 105: return new ObjectPermissionsPacket(header, bytes, ref i);
                        case 106: return new ObjectSaleInfoPacket(header, bytes, ref i);
                        case 107: return new ObjectNamePacket(header, bytes, ref i);
                        case 108: return new ObjectDescriptionPacket(header, bytes, ref i);
                        case 109: return new ObjectCategoryPacket(header, bytes, ref i);
                        case 110: return new ObjectSelectPacket(header, bytes, ref i);
                        case 111: return new ObjectDeselectPacket(header, bytes, ref i);
                        case 112: return new ObjectAttachPacket(header, bytes, ref i);
                        case 113: return new ObjectDetachPacket(header, bytes, ref i);
                        case 114: return new ObjectDropPacket(header, bytes, ref i);
                        case 115: return new ObjectLinkPacket(header, bytes, ref i);
                        case 116: return new ObjectDelinkPacket(header, bytes, ref i);
                        case 117: return new ObjectGrabPacket(header, bytes, ref i);
                        case 118: return new ObjectGrabUpdatePacket(header, bytes, ref i);
                        case 119: return new ObjectDeGrabPacket(header, bytes, ref i);
                        case 120: return new ObjectSpinStartPacket(header, bytes, ref i);
                        case 121: return new ObjectSpinUpdatePacket(header, bytes, ref i);
                        case 122: return new ObjectSpinStopPacket(header, bytes, ref i);
                        case 123: return new ObjectExportSelectedPacket(header, bytes, ref i);
                        case 124: return new ModifyLandPacket(header, bytes, ref i);
                        case 125: return new VelocityInterpolateOnPacket(header, bytes, ref i);
                        case 126: return new VelocityInterpolateOffPacket(header, bytes, ref i);
                        case 127: return new StateSavePacket(header, bytes, ref i);
                        case 128: return new ReportAutosaveCrashPacket(header, bytes, ref i);
                        case 129: return new SimWideDeletesPacket(header, bytes, ref i);
                        case 130: return new TrackAgentPacket(header, bytes, ref i);
                        case 131: return new ViewerStatsPacket(header, bytes, ref i);
                        case 132: return new ScriptAnswerYesPacket(header, bytes, ref i);
                        case 133: return new UserReportPacket(header, bytes, ref i);
                        case 134: return new AlertMessagePacket(header, bytes, ref i);
                        case 135: return new AgentAlertMessagePacket(header, bytes, ref i);
                        case 136: return new MeanCollisionAlertPacket(header, bytes, ref i);
                        case 137: return new ViewerFrozenMessagePacket(header, bytes, ref i);
                        case 138: return new HealthMessagePacket(header, bytes, ref i);
                        case 139: return new ChatFromSimulatorPacket(header, bytes, ref i);
                        case 140: return new SimStatsPacket(header, bytes, ref i);
                        case 141: return new RequestRegionInfoPacket(header, bytes, ref i);
                        case 142: return new RegionInfoPacket(header, bytes, ref i);
                        case 143: return new GodUpdateRegionInfoPacket(header, bytes, ref i);
                        case 148: return new RegionHandshakePacket(header, bytes, ref i);
                        case 149: return new RegionHandshakeReplyPacket(header, bytes, ref i);
                        case 150: return new SimulatorViewerTimeMessagePacket(header, bytes, ref i);
                        case 151: return new EnableSimulatorPacket(header, bytes, ref i);
                        case 152: return new DisableSimulatorPacket(header, bytes, ref i);
                        case 153: return new TransferRequestPacket(header, bytes, ref i);
                        case 154: return new TransferInfoPacket(header, bytes, ref i);
                        case 155: return new TransferAbortPacket(header, bytes, ref i);
                        case 156: return new RequestXferPacket(header, bytes, ref i);
                        case 157: return new AbortXferPacket(header, bytes, ref i);
                        case 158: return new AvatarAppearancePacket(header, bytes, ref i);
                        case 159: return new SetFollowCamPropertiesPacket(header, bytes, ref i);
                        case 160: return new ClearFollowCamPropertiesPacket(header, bytes, ref i);
                        case 161: return new RequestPayPricePacket(header, bytes, ref i);
                        case 162: return new PayPriceReplyPacket(header, bytes, ref i);
                        case 163: return new KickUserPacket(header, bytes, ref i);
                        case 165: return new GodKickUserPacket(header, bytes, ref i);
                        case 167: return new EjectUserPacket(header, bytes, ref i);
                        case 168: return new FreezeUserPacket(header, bytes, ref i);
                        case 169: return new AvatarPropertiesRequestPacket(header, bytes, ref i);
                        case 171: return new AvatarPropertiesReplyPacket(header, bytes, ref i);
                        case 172: return new AvatarInterestsReplyPacket(header, bytes, ref i);
                        case 173: return new AvatarGroupsReplyPacket(header, bytes, ref i);
                        case 174: return new AvatarPropertiesUpdatePacket(header, bytes, ref i);
                        case 175: return new AvatarInterestsUpdatePacket(header, bytes, ref i);
                        case 176: return new AvatarNotesReplyPacket(header, bytes, ref i);
                        case 177: return new AvatarNotesUpdatePacket(header, bytes, ref i);
                        case 178: return new AvatarPicksReplyPacket(header, bytes, ref i);
                        case 179: return new EventInfoRequestPacket(header, bytes, ref i);
                        case 180: return new EventInfoReplyPacket(header, bytes, ref i);
                        case 181: return new EventNotificationAddRequestPacket(header, bytes, ref i);
                        case 182: return new EventNotificationRemoveRequestPacket(header, bytes, ref i);
                        case 183: return new EventGodDeletePacket(header, bytes, ref i);
                        case 184: return new PickInfoReplyPacket(header, bytes, ref i);
                        case 185: return new PickInfoUpdatePacket(header, bytes, ref i);
                        case 186: return new PickDeletePacket(header, bytes, ref i);
                        case 187: return new PickGodDeletePacket(header, bytes, ref i);
                        case 188: return new ScriptQuestionPacket(header, bytes, ref i);
                        case 189: return new ScriptControlChangePacket(header, bytes, ref i);
                        case 190: return new ScriptDialogPacket(header, bytes, ref i);
                        case 191: return new ScriptDialogReplyPacket(header, bytes, ref i);
                        case 192: return new ForceScriptControlReleasePacket(header, bytes, ref i);
                        case 193: return new RevokePermissionsPacket(header, bytes, ref i);
                        case 194: return new LoadURLPacket(header, bytes, ref i);
                        case 195: return new ScriptTeleportRequestPacket(header, bytes, ref i);
                        case 196: return new ParcelOverlayPacket(header, bytes, ref i);
                        case 197: return new ParcelPropertiesRequestByIDPacket(header, bytes, ref i);
                        case 198: return new ParcelPropertiesUpdatePacket(header, bytes, ref i);
                        case 199: return new ParcelReturnObjectsPacket(header, bytes, ref i);
                        case 200: return new ParcelSetOtherCleanTimePacket(header, bytes, ref i);
                        case 201: return new ParcelDisableObjectsPacket(header, bytes, ref i);
                        case 202: return new ParcelSelectObjectsPacket(header, bytes, ref i);
                        case 203: return new EstateCovenantRequestPacket(header, bytes, ref i);
                        case 204: return new EstateCovenantReplyPacket(header, bytes, ref i);
                        case 205: return new ForceObjectSelectPacket(header, bytes, ref i);
                        case 206: return new ParcelBuyPassPacket(header, bytes, ref i);
                        case 207: return new ParcelDeedToGroupPacket(header, bytes, ref i);
                        case 208: return new ParcelReclaimPacket(header, bytes, ref i);
                        case 209: return new ParcelClaimPacket(header, bytes, ref i);
                        case 210: return new ParcelJoinPacket(header, bytes, ref i);
                        case 211: return new ParcelDividePacket(header, bytes, ref i);
                        case 212: return new ParcelReleasePacket(header, bytes, ref i);
                        case 213: return new ParcelBuyPacket(header, bytes, ref i);
                        case 214: return new ParcelGodForceOwnerPacket(header, bytes, ref i);
                        case 215: return new ParcelAccessListRequestPacket(header, bytes, ref i);
                        case 216: return new ParcelAccessListReplyPacket(header, bytes, ref i);
                        case 217: return new ParcelAccessListUpdatePacket(header, bytes, ref i);
                        case 218: return new ParcelDwellRequestPacket(header, bytes, ref i);
                        case 219: return new ParcelDwellReplyPacket(header, bytes, ref i);
                        case 227: return new ParcelGodMarkAsContentPacket(header, bytes, ref i);
                        case 228: return new ViewerStartAuctionPacket(header, bytes, ref i);
                        case 235: return new UUIDNameRequestPacket(header, bytes, ref i);
                        case 236: return new UUIDNameReplyPacket(header, bytes, ref i);
                        case 237: return new UUIDGroupNameRequestPacket(header, bytes, ref i);
                        case 238: return new UUIDGroupNameReplyPacket(header, bytes, ref i);
                        case 240: return new ChildAgentDyingPacket(header, bytes, ref i);
                        case 241: return new ChildAgentUnknownPacket(header, bytes, ref i);
                        case 243: return new GetScriptRunningPacket(header, bytes, ref i);
                        case 244: return new ScriptRunningReplyPacket(header, bytes, ref i);
                        case 245: return new SetScriptRunningPacket(header, bytes, ref i);
                        case 246: return new ScriptResetPacket(header, bytes, ref i);
                        case 247: return new ScriptSensorRequestPacket(header, bytes, ref i);
                        case 248: return new ScriptSensorReplyPacket(header, bytes, ref i);
                        case 249: return new CompleteAgentMovementPacket(header, bytes, ref i);
                        case 250: return new AgentMovementCompletePacket(header, bytes, ref i);
                        case 252: return new LogoutRequestPacket(header, bytes, ref i);
                        case 253: return new LogoutReplyPacket(header, bytes, ref i);
                        case 254: return new ImprovedInstantMessagePacket(header, bytes, ref i);
                        case 255: return new RetrieveInstantMessagesPacket(header, bytes, ref i);
                        case 256: return new FindAgentPacket(header, bytes, ref i);
                        case 257: return new RequestGodlikePowersPacket(header, bytes, ref i);
                        case 258: return new GrantGodlikePowersPacket(header, bytes, ref i);
                        case 259: return new GodlikeMessagePacket(header, bytes, ref i);
                        case 260: return new EstateOwnerMessagePacket(header, bytes, ref i);
                        case 261: return new GenericMessagePacket(header, bytes, ref i);
                        case 262: return new MuteListRequestPacket(header, bytes, ref i);
                        case 263: return new UpdateMuteListEntryPacket(header, bytes, ref i);
                        case 264: return new RemoveMuteListEntryPacket(header, bytes, ref i);
                        case 265: return new CopyInventoryFromNotecardPacket(header, bytes, ref i);
                        case 266: return new UpdateInventoryItemPacket(header, bytes, ref i);
                        case 267: return new UpdateCreateInventoryItemPacket(header, bytes, ref i);
                        case 268: return new MoveInventoryItemPacket(header, bytes, ref i);
                        case 269: return new CopyInventoryItemPacket(header, bytes, ref i);
                        case 270: return new RemoveInventoryItemPacket(header, bytes, ref i);
                        case 271: return new ChangeInventoryItemFlagsPacket(header, bytes, ref i);
                        case 272: return new SaveAssetIntoInventoryPacket(header, bytes, ref i);
                        case 273: return new CreateInventoryFolderPacket(header, bytes, ref i);
                        case 274: return new UpdateInventoryFolderPacket(header, bytes, ref i);
                        case 275: return new MoveInventoryFolderPacket(header, bytes, ref i);
                        case 276: return new RemoveInventoryFolderPacket(header, bytes, ref i);
                        case 277: return new FetchInventoryDescendentsPacket(header, bytes, ref i);
                        case 278: return new InventoryDescendentsPacket(header, bytes, ref i);
                        case 279: return new FetchInventoryPacket(header, bytes, ref i);
                        case 280: return new FetchInventoryReplyPacket(header, bytes, ref i);
                        case 281: return new BulkUpdateInventoryPacket(header, bytes, ref i);
                        case 284: return new RemoveInventoryObjectsPacket(header, bytes, ref i);
                        case 285: return new PurgeInventoryDescendentsPacket(header, bytes, ref i);
                        case 286: return new UpdateTaskInventoryPacket(header, bytes, ref i);
                        case 287: return new RemoveTaskInventoryPacket(header, bytes, ref i);
                        case 288: return new MoveTaskInventoryPacket(header, bytes, ref i);
                        case 289: return new RequestTaskInventoryPacket(header, bytes, ref i);
                        case 290: return new ReplyTaskInventoryPacket(header, bytes, ref i);
                        case 291: return new DeRezObjectPacket(header, bytes, ref i);
                        case 292: return new DeRezAckPacket(header, bytes, ref i);
                        case 293: return new RezObjectPacket(header, bytes, ref i);
                        case 294: return new RezObjectFromNotecardPacket(header, bytes, ref i);
                        case 297: return new AcceptFriendshipPacket(header, bytes, ref i);
                        case 298: return new DeclineFriendshipPacket(header, bytes, ref i);
                        case 300: return new TerminateFriendshipPacket(header, bytes, ref i);
                        case 301: return new OfferCallingCardPacket(header, bytes, ref i);
                        case 302: return new AcceptCallingCardPacket(header, bytes, ref i);
                        case 303: return new DeclineCallingCardPacket(header, bytes, ref i);
                        case 304: return new RezScriptPacket(header, bytes, ref i);
                        case 305: return new CreateInventoryItemPacket(header, bytes, ref i);
                        case 306: return new CreateLandmarkForEventPacket(header, bytes, ref i);
                        case 309: return new RegionHandleRequestPacket(header, bytes, ref i);
                        case 310: return new RegionIDAndHandleReplyPacket(header, bytes, ref i);
                        case 311: return new MoneyTransferRequestPacket(header, bytes, ref i);
                        case 313: return new MoneyBalanceRequestPacket(header, bytes, ref i);
                        case 314: return new MoneyBalanceReplyPacket(header, bytes, ref i);
                        case 315: return new RoutedMoneyBalanceReplyPacket(header, bytes, ref i);
                        case 316: return new ActivateGesturesPacket(header, bytes, ref i);
                        case 317: return new DeactivateGesturesPacket(header, bytes, ref i);
                        case 318: return new MuteListUpdatePacket(header, bytes, ref i);
                        case 319: return new UseCachedMuteListPacket(header, bytes, ref i);
                        case 320: return new GrantUserRightsPacket(header, bytes, ref i);
                        case 321: return new ChangeUserRightsPacket(header, bytes, ref i);
                        case 322: return new OnlineNotificationPacket(header, bytes, ref i);
                        case 323: return new OfflineNotificationPacket(header, bytes, ref i);
                        case 324: return new SetStartLocationRequestPacket(header, bytes, ref i);
                        case 333: return new AssetUploadRequestPacket(header, bytes, ref i);
                        case 334: return new AssetUploadCompletePacket(header, bytes, ref i);
                        case 339: return new CreateGroupRequestPacket(header, bytes, ref i);
                        case 340: return new CreateGroupReplyPacket(header, bytes, ref i);
                        case 341: return new UpdateGroupInfoPacket(header, bytes, ref i);
                        case 342: return new GroupRoleChangesPacket(header, bytes, ref i);
                        case 343: return new JoinGroupRequestPacket(header, bytes, ref i);
                        case 344: return new JoinGroupReplyPacket(header, bytes, ref i);
                        case 345: return new EjectGroupMemberRequestPacket(header, bytes, ref i);
                        case 346: return new EjectGroupMemberReplyPacket(header, bytes, ref i);
                        case 347: return new LeaveGroupRequestPacket(header, bytes, ref i);
                        case 348: return new LeaveGroupReplyPacket(header, bytes, ref i);
                        case 349: return new InviteGroupRequestPacket(header, bytes, ref i);
                        case 351: return new GroupProfileRequestPacket(header, bytes, ref i);
                        case 352: return new GroupProfileReplyPacket(header, bytes, ref i);
                        case 353: return new GroupAccountSummaryRequestPacket(header, bytes, ref i);
                        case 354: return new GroupAccountSummaryReplyPacket(header, bytes, ref i);
                        case 355: return new GroupAccountDetailsRequestPacket(header, bytes, ref i);
                        case 356: return new GroupAccountDetailsReplyPacket(header, bytes, ref i);
                        case 357: return new GroupAccountTransactionsRequestPacket(header, bytes, ref i);
                        case 358: return new GroupAccountTransactionsReplyPacket(header, bytes, ref i);
                        case 359: return new GroupActiveProposalsRequestPacket(header, bytes, ref i);
                        case 360: return new GroupActiveProposalItemReplyPacket(header, bytes, ref i);
                        case 361: return new GroupVoteHistoryRequestPacket(header, bytes, ref i);
                        case 362: return new GroupVoteHistoryItemReplyPacket(header, bytes, ref i);
                        case 363: return new StartGroupProposalPacket(header, bytes, ref i);
                        case 364: return new GroupProposalBallotPacket(header, bytes, ref i);
                        case 366: return new GroupMembersRequestPacket(header, bytes, ref i);
                        case 367: return new GroupMembersReplyPacket(header, bytes, ref i);
                        case 368: return new ActivateGroupPacket(header, bytes, ref i);
                        case 369: return new SetGroupContributionPacket(header, bytes, ref i);
                        case 370: return new SetGroupAcceptNoticesPacket(header, bytes, ref i);
                        case 371: return new GroupRoleDataRequestPacket(header, bytes, ref i);
                        case 372: return new GroupRoleDataReplyPacket(header, bytes, ref i);
                        case 373: return new GroupRoleMembersRequestPacket(header, bytes, ref i);
                        case 374: return new GroupRoleMembersReplyPacket(header, bytes, ref i);
                        case 375: return new GroupTitlesRequestPacket(header, bytes, ref i);
                        case 376: return new GroupTitlesReplyPacket(header, bytes, ref i);
                        case 377: return new GroupTitleUpdatePacket(header, bytes, ref i);
                        case 378: return new GroupRoleUpdatePacket(header, bytes, ref i);
                        case 379: return new LiveHelpGroupRequestPacket(header, bytes, ref i);
                        case 380: return new LiveHelpGroupReplyPacket(header, bytes, ref i);
                        case 381: return new AgentWearablesRequestPacket(header, bytes, ref i);
                        case 382: return new AgentWearablesUpdatePacket(header, bytes, ref i);
                        case 383: return new AgentIsNowWearingPacket(header, bytes, ref i);
                        case 384: return new AgentCachedTexturePacket(header, bytes, ref i);
                        case 385: return new AgentCachedTextureResponsePacket(header, bytes, ref i);
                        case 386: return new AgentDataUpdateRequestPacket(header, bytes, ref i);
                        case 387: return new AgentDataUpdatePacket(header, bytes, ref i);
                        case 388: return new GroupDataUpdatePacket(header, bytes, ref i);
                        case 389: return new AgentGroupDataUpdatePacket(header, bytes, ref i);
                        case 390: return new AgentDropGroupPacket(header, bytes, ref i);
                        case 395: return new RezSingleAttachmentFromInvPacket(header, bytes, ref i);
                        case 396: return new RezMultipleAttachmentsFromInvPacket(header, bytes, ref i);
                        case 397: return new DetachAttachmentIntoInvPacket(header, bytes, ref i);
                        case 398: return new CreateNewOutfitAttachmentsPacket(header, bytes, ref i);
                        case 399: return new UserInfoRequestPacket(header, bytes, ref i);
                        case 400: return new UserInfoReplyPacket(header, bytes, ref i);
                        case 401: return new UpdateUserInfoPacket(header, bytes, ref i);
                        case 403: return new InitiateDownloadPacket(header, bytes, ref i);
                        case 405: return new MapLayerRequestPacket(header, bytes, ref i);
                        case 406: return new MapLayerReplyPacket(header, bytes, ref i);
                        case 407: return new MapBlockRequestPacket(header, bytes, ref i);
                        case 408: return new MapNameRequestPacket(header, bytes, ref i);
                        case 409: return new MapBlockReplyPacket(header, bytes, ref i);
                        case 410: return new MapItemRequestPacket(header, bytes, ref i);
                        case 411: return new MapItemReplyPacket(header, bytes, ref i);
                        case 412: return new SendPostcardPacket(header, bytes, ref i);
                        case 419: return new ParcelMediaCommandMessagePacket(header, bytes, ref i);
                        case 420: return new ParcelMediaUpdatePacket(header, bytes, ref i);
                        case 421: return new LandStatRequestPacket(header, bytes, ref i);
                        case 422: return new LandStatReplyPacket(header, bytes, ref i);
                        case 423: return new ErrorPacket(header, bytes, ref i);
                        case 424: return new ObjectIncludeInSearchPacket(header, bytes, ref i);
                        case 425: return new RezRestoreToWorldPacket(header, bytes, ref i);
                        case 426: return new LinkInventoryItemPacket(header, bytes, ref i);
                        case 65531: return new PacketAckPacket(header, bytes, ref i);
                        case 65532: return new OpenCircuitPacket(header, bytes, ref i);
                        case 65533: return new CloseCircuitPacket(header, bytes, ref i);

                    }
                    break;
                case PacketFrequency.Medium:
                    switch (header.ID)
                    {
                        case 1: return new ObjectAddPacket(header, bytes, ref i);
                        case 2: return new MultipleObjectUpdatePacket(header, bytes, ref i);
                        case 3: return new RequestMultipleObjectsPacket(header, bytes, ref i);
                        case 4: return new ObjectPositionPacket(header, bytes, ref i);
                        case 5: return new RequestObjectPropertiesFamilyPacket(header, bytes, ref i);
                        case 6: return new CoarseLocationUpdatePacket(header, bytes, ref i);
                        case 7: return new CrossedRegionPacket(header, bytes, ref i);
                        case 8: return new ConfirmEnableSimulatorPacket(header, bytes, ref i);
                        case 9: return new ObjectPropertiesPacket(header, bytes, ref i);
                        case 10: return new ObjectPropertiesFamilyPacket(header, bytes, ref i);
                        case 11: return new ParcelPropertiesRequestPacket(header, bytes, ref i);
                        case 13: return new AttachedSoundPacket(header, bytes, ref i);
                        case 14: return new AttachedSoundGainChangePacket(header, bytes, ref i);
                        case 15: return new PreloadSoundPacket(header, bytes, ref i);
                        case 17: return new ViewerEffectPacket(header, bytes, ref i);

                    }
                    break;
                case PacketFrequency.High:
                    switch (header.ID)
                    {
                        case 1: return new StartPingCheckPacket(header, bytes, ref i);
                        case 2: return new CompletePingCheckPacket(header, bytes, ref i);
                        case 4: return new AgentUpdatePacket(header, bytes, ref i);
                        case 5: return new AgentAnimationPacket(header, bytes, ref i);
                        case 6: return new AgentRequestSitPacket(header, bytes, ref i);
                        case 7: return new AgentSitPacket(header, bytes, ref i);
                        case 8: return new RequestImagePacket(header, bytes, ref i);
                        case 9: return new ImageDataPacket(header, bytes, ref i);
                        case 10: return new ImagePacketPacket(header, bytes, ref i);
                        case 11: return new LayerDataPacket(header, bytes, ref i);
                        case 12: return new ObjectUpdatePacket(header, bytes, ref i);
                        case 13: return new ObjectUpdateCompressedPacket(header, bytes, ref i);
                        case 14: return new ObjectUpdateCachedPacket(header, bytes, ref i);
                        case 15: return new ImprovedTerseObjectUpdatePacket(header, bytes, ref i);
                        case 16: return new KillObjectPacket(header, bytes, ref i);
                        case 17: return new TransferPacketPacket(header, bytes, ref i);
                        case 18: return new SendXferPacketPacket(header, bytes, ref i);
                        case 19: return new ConfirmXferPacketPacket(header, bytes, ref i);
                        case 20: return new AvatarAnimationPacket(header, bytes, ref i);
                        case 21: return new AvatarSitResponsePacket(header, bytes, ref i);
                        case 22: return new CameraConstraintPacket(header, bytes, ref i);
                        case 23: return new ParcelPropertiesPacket(header, bytes, ref i);
                        case 25: return new ChildAgentUpdatePacket(header, bytes, ref i);
                        case 26: return new ChildAgentAlivePacket(header, bytes, ref i);
                        case 27: return new ChildAgentPositionUpdatePacket(header, bytes, ref i);
                        case 29: return new SoundTriggerPacket(header, bytes, ref i);

                    }
                    break;
            }

            throw new MalformedDataException("Unknown packet ID " + header.Frequency + " " + header.ID);
        }
    }
    /// <exclude/>
    public sealed class TestMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class TestBlock1Block : PacketBlock
        {
            public uint Test1;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public TestBlock1Block() { }
            public TestBlock1Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Test1 = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Test1, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class NeighborBlockBlock : PacketBlock
        {
            public uint Test0;
            public uint Test1;
            public uint Test2;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public NeighborBlockBlock() { }
            public NeighborBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Test0 = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Test1 = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Test2 = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Test0, bytes, i); i += 4;
                Utils.UIntToBytes(Test1, bytes, i); i += 4;
                Utils.UIntToBytes(Test2, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TestBlock1.Length;
                for (int j = 0; j < 4; j++)
                    length += NeighborBlock[j].Length;
                return length;
            }
        }
        public TestBlock1Block TestBlock1;
        public NeighborBlockBlock[] NeighborBlock;

        public TestMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TestMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 1;
            Header.Reliable = true;
            Header.Zerocoded = true;
            TestBlock1 = new TestBlock1Block();
            NeighborBlock = new NeighborBlockBlock[4];
        }

        public TestMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TestBlock1.FromBytes(bytes, ref i);
            if(NeighborBlock == null || NeighborBlock.Length != 4) {
                NeighborBlock = new NeighborBlockBlock[4];
                for(int j = 0; j < 4; j++)
                { NeighborBlock[j] = new NeighborBlockBlock(); }
            }
            for (int j = 0; j < 4; j++)
            { NeighborBlock[j].FromBytes(bytes, ref i); }
        }

        public TestMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TestBlock1.FromBytes(bytes, ref i);
            if(NeighborBlock == null || NeighborBlock.Length != 4) {
                NeighborBlock = new NeighborBlockBlock[4];
                for(int j = 0; j < 4; j++)
                { NeighborBlock[j] = new NeighborBlockBlock(); }
            }
            for (int j = 0; j < 4; j++)
            { NeighborBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TestBlock1.Length;
            for (int j = 0; j < 4; j++) { length += NeighborBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TestBlock1.ToBytes(bytes, ref i);
            for (int j = 0; j < 4; j++) { NeighborBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UseCircuitCodePacket : Packet
    {
        /// <exclude/>
        public sealed class CircuitCodeBlock : PacketBlock
        {
            public uint Code;
            public UUID SessionID;
            public UUID ID;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public CircuitCodeBlock() { }
            public CircuitCodeBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Code = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SessionID.FromBytes(bytes, i); i += 16;
                    ID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Code, bytes, i); i += 4;
                SessionID.ToBytes(bytes, i); i += 16;
                ID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += CircuitCode.Length;
                return length;
            }
        }
        public CircuitCodeBlock CircuitCode;

        public UseCircuitCodePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UseCircuitCode;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 3;
            Header.Reliable = true;
            CircuitCode = new CircuitCodeBlock();
        }

        public UseCircuitCodePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            CircuitCode.FromBytes(bytes, ref i);
        }

        public UseCircuitCodePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            CircuitCode.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += CircuitCode.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            CircuitCode.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TelehubInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class TelehubBlockBlock : PacketBlock
        {
            public UUID ObjectID;
            public byte[] ObjectName;
            public Vector3 TelehubPos;
            public Quaternion TelehubRot;

            public override int Length
            {
                get
                {
                    int length = 41;
                    if (ObjectName != null) { length += ObjectName.Length; }
                    return length;
                }
            }

            public TelehubBlockBlock() { }
            public TelehubBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    ObjectName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectName, 0, length); i += length;
                    TelehubPos.FromBytes(bytes, i); i += 12;
                    TelehubRot.FromBytes(bytes, i, true); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)ObjectName.Length;
                Buffer.BlockCopy(ObjectName, 0, bytes, i, ObjectName.Length); i += ObjectName.Length;
                TelehubPos.ToBytes(bytes, i); i += 12;
                TelehubRot.ToBytes(bytes, i); i += 12;
            }

        }

        /// <exclude/>
        public sealed class SpawnPointBlockBlock : PacketBlock
        {
            public Vector3 SpawnPointPos;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public SpawnPointBlockBlock() { }
            public SpawnPointBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SpawnPointPos.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                SpawnPointPos.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += TelehubBlock.Length;
                for (int j = 0; j < SpawnPointBlock.Length; j++)
                    length += SpawnPointBlock[j].Length;
                return length;
            }
        }
        public TelehubBlockBlock TelehubBlock;
        public SpawnPointBlockBlock[] SpawnPointBlock;

        public TelehubInfoPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.TelehubInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 10;
            Header.Reliable = true;
            TelehubBlock = new TelehubBlockBlock();
            SpawnPointBlock = null;
        }

        public TelehubInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TelehubBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SpawnPointBlock == null || SpawnPointBlock.Length != -1) {
                SpawnPointBlock = new SpawnPointBlockBlock[count];
                for(int j = 0; j < count; j++)
                { SpawnPointBlock[j] = new SpawnPointBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SpawnPointBlock[j].FromBytes(bytes, ref i); }
        }

        public TelehubInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TelehubBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SpawnPointBlock == null || SpawnPointBlock.Length != count) {
                SpawnPointBlock = new SpawnPointBlockBlock[count];
                for(int j = 0; j < count; j++)
                { SpawnPointBlock[j] = new SpawnPointBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SpawnPointBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TelehubBlock.Length;
            length++;
            for (int j = 0; j < SpawnPointBlock.Length; j++) { length += SpawnPointBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TelehubBlock.ToBytes(bytes, ref i);
            bytes[i++] = (byte)SpawnPointBlock.Length;
            for (int j = 0; j < SpawnPointBlock.Length; j++) { SpawnPointBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += TelehubBlock.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            TelehubBlock.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int SpawnPointBlockStart = 0;
            do
            {
                int variableLength = 0;
                int SpawnPointBlockCount = 0;

                i = SpawnPointBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < SpawnPointBlock.Length) {
                    int blockLength = SpawnPointBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++SpawnPointBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)SpawnPointBlockCount;
                for (i = SpawnPointBlockStart; i < SpawnPointBlockStart + SpawnPointBlockCount; i++) { SpawnPointBlock[i].ToBytes(packet, ref length); }
                SpawnPointBlockStart += SpawnPointBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                SpawnPointBlockStart < SpawnPointBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class EconomyDataRequestPacket : Packet
    {
        public override int Length
        {
            get
            {
                int length = 10;
                return length;
            }
        }

        public EconomyDataRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EconomyDataRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 24;
            Header.Reliable = true;
        }

        public EconomyDataRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
        }

        public EconomyDataRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EconomyDataPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public int ObjectCapacity;
            public int ObjectCount;
            public int PriceEnergyUnit;
            public int PriceObjectClaim;
            public int PricePublicObjectDecay;
            public int PricePublicObjectDelete;
            public int PriceParcelClaim;
            public float PriceParcelClaimFactor;
            public int PriceUpload;
            public int PriceRentLight;
            public int TeleportMinPrice;
            public float TeleportPriceExponent;
            public float EnergyEfficiency;
            public float PriceObjectRent;
            public float PriceObjectScaleFactor;
            public int PriceParcelRent;
            public int PriceGroupCreate;

            public override int Length
            {
                get
                {
                    return 68;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectCapacity = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ObjectCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceEnergyUnit = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceObjectClaim = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PricePublicObjectDecay = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PricePublicObjectDelete = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceParcelClaim = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceParcelClaimFactor = Utils.BytesToFloat(bytes, i); i += 4;
                    PriceUpload = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceRentLight = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TeleportMinPrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TeleportPriceExponent = Utils.BytesToFloat(bytes, i); i += 4;
                    EnergyEfficiency = Utils.BytesToFloat(bytes, i); i += 4;
                    PriceObjectRent = Utils.BytesToFloat(bytes, i); i += 4;
                    PriceObjectScaleFactor = Utils.BytesToFloat(bytes, i); i += 4;
                    PriceParcelRent = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceGroupCreate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(ObjectCapacity, bytes, i); i += 4;
                Utils.IntToBytes(ObjectCount, bytes, i); i += 4;
                Utils.IntToBytes(PriceEnergyUnit, bytes, i); i += 4;
                Utils.IntToBytes(PriceObjectClaim, bytes, i); i += 4;
                Utils.IntToBytes(PricePublicObjectDecay, bytes, i); i += 4;
                Utils.IntToBytes(PricePublicObjectDelete, bytes, i); i += 4;
                Utils.IntToBytes(PriceParcelClaim, bytes, i); i += 4;
                Utils.FloatToBytes(PriceParcelClaimFactor, bytes, i); i += 4;
                Utils.IntToBytes(PriceUpload, bytes, i); i += 4;
                Utils.IntToBytes(PriceRentLight, bytes, i); i += 4;
                Utils.IntToBytes(TeleportMinPrice, bytes, i); i += 4;
                Utils.FloatToBytes(TeleportPriceExponent, bytes, i); i += 4;
                Utils.FloatToBytes(EnergyEfficiency, bytes, i); i += 4;
                Utils.FloatToBytes(PriceObjectRent, bytes, i); i += 4;
                Utils.FloatToBytes(PriceObjectScaleFactor, bytes, i); i += 4;
                Utils.IntToBytes(PriceParcelRent, bytes, i); i += 4;
                Utils.IntToBytes(PriceGroupCreate, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public EconomyDataPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EconomyData;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 25;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Info = new InfoBlock();
        }

        public EconomyDataPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public EconomyDataPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarPickerRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public AvatarPickerRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarPickerRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 26;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public AvatarPickerRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public AvatarPickerRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarPickerReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID AvatarID;
            public byte[] FirstName;
            public byte[] LastName;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (FirstName != null) { length += FirstName.Length; }
                    if (LastName != null) { length += LastName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AvatarID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    FirstName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FirstName, 0, length); i += length;
                    length = bytes[i++];
                    LastName = new byte[length];
                    Buffer.BlockCopy(bytes, i, LastName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AvatarID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)FirstName.Length;
                Buffer.BlockCopy(FirstName, 0, bytes, i, FirstName.Length); i += FirstName.Length;
                bytes[i++] = (byte)LastName.Length;
                Buffer.BlockCopy(LastName, 0, bytes, i, LastName.Length); i += LastName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;

        public AvatarPickerReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AvatarPickerReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 28;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
        }

        public AvatarPickerReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public AvatarPickerReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class PlacesQueryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public byte[] QueryText;
            public uint QueryFlags;
            public sbyte Category;
            public byte[] SimName;

            public override int Length
            {
                get
                {
                    int length = 7;
                    if (QueryText != null) { length += QueryText.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    QueryText = new byte[length];
                    Buffer.BlockCopy(bytes, i, QueryText, 0, length); i += length;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Category = (sbyte)bytes[i++];
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)QueryText.Length;
                Buffer.BlockCopy(QueryText, 0, bytes, i, QueryText.Length); i += QueryText.Length;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
                bytes[i++] = (byte)Category;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += TransactionData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionDataBlock TransactionData;
        public QueryDataBlock QueryData;

        public PlacesQueryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.PlacesQuery;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 29;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            TransactionData = new TransactionDataBlock();
            QueryData = new QueryDataBlock();
        }

        public PlacesQueryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public PlacesQueryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PlacesReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID OwnerID;
            public byte[] Name;
            public byte[] Desc;
            public int ActualArea;
            public int BillableArea;
            public byte Flags;
            public float GlobalX;
            public float GlobalY;
            public float GlobalZ;
            public byte[] SimName;
            public UUID SnapshotID;
            public float Dwell;
            public int Price;

            public override int Length
            {
                get
                {
                    int length = 64;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    ActualArea = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    BillableArea = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (byte)bytes[i++];
                    GlobalX = Utils.BytesToFloat(bytes, i); i += 4;
                    GlobalY = Utils.BytesToFloat(bytes, i); i += 4;
                    GlobalZ = Utils.BytesToFloat(bytes, i); i += 4;
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    Dwell = Utils.BytesToFloat(bytes, i); i += 4;
                    Price = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Desc.Length;
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                Utils.IntToBytes(ActualArea, bytes, i); i += 4;
                Utils.IntToBytes(BillableArea, bytes, i); i += 4;
                bytes[i++] = Flags;
                Utils.FloatToBytes(GlobalX, bytes, i); i += 4;
                Utils.FloatToBytes(GlobalY, bytes, i); i += 4;
                Utils.FloatToBytes(GlobalZ, bytes, i); i += 4;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                SnapshotID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(Dwell, bytes, i); i += 4;
                Utils.IntToBytes(Price, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += TransactionData.Length;
                for (int j = 0; j < QueryData.Length; j++)
                    length += QueryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionDataBlock TransactionData;
        public QueryDataBlock[] QueryData;

        public PlacesReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.PlacesReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 30;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            TransactionData = new TransactionDataBlock();
            QueryData = null;
        }

        public PlacesReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryData == null || QueryData.Length != -1) {
                QueryData = new QueryDataBlock[count];
                for(int j = 0; j < count; j++)
                { QueryData[j] = new QueryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryData[j].FromBytes(bytes, ref i); }
        }

        public PlacesReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryData == null || QueryData.Length != count) {
                QueryData = new QueryDataBlock[count];
                for(int j = 0; j < count; j++)
                { QueryData[j] = new QueryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionData.Length;
            length++;
            for (int j = 0; j < QueryData.Length; j++) { length += QueryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryData.Length;
            for (int j = 0; j < QueryData.Length; j++) { QueryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += TransactionData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            TransactionData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int QueryDataStart = 0;
            do
            {
                int variableLength = 0;
                int QueryDataCount = 0;

                i = QueryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryData.Length) {
                    int blockLength = QueryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryDataCount;
                for (i = QueryDataStart; i < QueryDataStart + QueryDataCount; i++) { QueryData[i].ToBytes(packet, ref length); }
                QueryDataStart += QueryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryDataStart < QueryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DirFindQueryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;
            public byte[] QueryText;
            public uint QueryFlags;
            public int QueryStart;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (QueryText != null) { length += QueryText.Length; }
                    return length;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    QueryText = new byte[length];
                    Buffer.BlockCopy(bytes, i, QueryText, 0, length); i += length;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    QueryStart = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)QueryText.Length;
                Buffer.BlockCopy(QueryText, 0, bytes, i, QueryText.Length); i += QueryText.Length;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
                Utils.IntToBytes(QueryStart, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;

        public DirFindQueryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DirFindQuery;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 31;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
        }

        public DirFindQueryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public DirFindQueryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DirPlacesQueryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;
            public byte[] QueryText;
            public uint QueryFlags;
            public sbyte Category;
            public byte[] SimName;
            public int QueryStart;

            public override int Length
            {
                get
                {
                    int length = 27;
                    if (QueryText != null) { length += QueryText.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    QueryText = new byte[length];
                    Buffer.BlockCopy(bytes, i, QueryText, 0, length); i += length;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Category = (sbyte)bytes[i++];
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    QueryStart = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)QueryText.Length;
                Buffer.BlockCopy(QueryText, 0, bytes, i, QueryText.Length); i += QueryText.Length;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
                bytes[i++] = (byte)Category;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                Utils.IntToBytes(QueryStart, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;

        public DirPlacesQueryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DirPlacesQuery;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 33;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
        }

        public DirPlacesQueryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public DirPlacesQueryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DirPlacesReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID ParcelID;
            public byte[] Name;
            public bool ForSale;
            public bool Auction;
            public float Dwell;

            public override int Length
            {
                get
                {
                    int length = 23;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ParcelID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    ForSale = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Auction = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Dwell = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ParcelID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)((ForSale) ? 1 : 0);
                bytes[i++] = (byte)((Auction) ? 1 : 0);
                Utils.FloatToBytes(Dwell, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class StatusDataBlock : PacketBlock
        {
            public uint Status;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public StatusDataBlock() { }
            public StatusDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Status = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Status, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 13;
                length += AgentData.Length;
                for (int j = 0; j < QueryData.Length; j++)
                    length += QueryData[j].Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                for (int j = 0; j < StatusData.Length; j++)
                    length += StatusData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock[] QueryData;
        public QueryRepliesBlock[] QueryReplies;
        public StatusDataBlock[] StatusData;

        public DirPlacesReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirPlacesReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 35;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = null;
            QueryReplies = null;
            StatusData = null;
        }

        public DirPlacesReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryData == null || QueryData.Length != -1) {
                QueryData = new QueryDataBlock[count];
                for(int j = 0; j < count; j++)
                { QueryData[j] = new QueryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(StatusData == null || StatusData.Length != -1) {
                StatusData = new StatusDataBlock[count];
                for(int j = 0; j < count; j++)
                { StatusData[j] = new StatusDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { StatusData[j].FromBytes(bytes, ref i); }
        }

        public DirPlacesReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryData == null || QueryData.Length != count) {
                QueryData = new QueryDataBlock[count];
                for(int j = 0; j < count; j++)
                { QueryData[j] = new QueryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(StatusData == null || StatusData.Length != count) {
                StatusData = new StatusDataBlock[count];
                for(int j = 0; j < count; j++)
                { StatusData[j] = new StatusDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { StatusData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < QueryData.Length; j++) { length += QueryData[j].Length; }
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            length++;
            for (int j = 0; j < StatusData.Length; j++) { length += StatusData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryData.Length;
            for (int j = 0; j < QueryData.Length; j++) { QueryData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)StatusData.Length;
            for (int j = 0; j < StatusData.Length; j++) { StatusData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 3;

            int QueryDataStart = 0;
            int QueryRepliesStart = 0;
            int StatusDataStart = 0;
            do
            {
                int variableLength = 0;
                int QueryDataCount = 0;
                int QueryRepliesCount = 0;
                int StatusDataCount = 0;

                i = QueryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryData.Length) {
                    int blockLength = QueryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                i = StatusDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < StatusData.Length) {
                    int blockLength = StatusData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++StatusDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryDataCount;
                for (i = QueryDataStart; i < QueryDataStart + QueryDataCount; i++) { QueryData[i].ToBytes(packet, ref length); }
                QueryDataStart += QueryDataCount;

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                packet[length++] = (byte)StatusDataCount;
                for (i = StatusDataStart; i < StatusDataStart + StatusDataCount; i++) { StatusData[i].ToBytes(packet, ref length); }
                StatusDataStart += StatusDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryDataStart < QueryData.Length ||
                QueryRepliesStart < QueryReplies.Length ||
                StatusDataStart < StatusData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DirPeopleReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID AgentID;
            public byte[] FirstName;
            public byte[] LastName;
            public byte[] Group;
            public bool Online;
            public int Reputation;

            public override int Length
            {
                get
                {
                    int length = 24;
                    if (FirstName != null) { length += FirstName.Length; }
                    if (LastName != null) { length += LastName.Length; }
                    if (Group != null) { length += Group.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    FirstName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FirstName, 0, length); i += length;
                    length = bytes[i++];
                    LastName = new byte[length];
                    Buffer.BlockCopy(bytes, i, LastName, 0, length); i += length;
                    length = bytes[i++];
                    Group = new byte[length];
                    Buffer.BlockCopy(bytes, i, Group, 0, length); i += length;
                    Online = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Reputation = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)FirstName.Length;
                Buffer.BlockCopy(FirstName, 0, bytes, i, FirstName.Length); i += FirstName.Length;
                bytes[i++] = (byte)LastName.Length;
                Buffer.BlockCopy(LastName, 0, bytes, i, LastName.Length); i += LastName.Length;
                bytes[i++] = (byte)Group.Length;
                Buffer.BlockCopy(Group, 0, bytes, i, Group.Length); i += Group.Length;
                bytes[i++] = (byte)((Online) ? 1 : 0);
                Utils.IntToBytes(Reputation, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += QueryData.Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;
        public QueryRepliesBlock[] QueryReplies;

        public DirPeopleReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirPeopleReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 36;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
            QueryReplies = null;
        }

        public DirPeopleReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public DirPeopleReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += QueryData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            QueryData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int QueryRepliesStart = 0;
            do
            {
                int variableLength = 0;
                int QueryRepliesCount = 0;

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryRepliesStart < QueryReplies.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DirEventsReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID OwnerID;
            public byte[] Name;
            public uint EventID;
            public byte[] Date;
            public uint UnixTime;
            public uint EventFlags;

            public override int Length
            {
                get
                {
                    int length = 30;
                    if (Name != null) { length += Name.Length; }
                    if (Date != null) { length += Date.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Date = new byte[length];
                    Buffer.BlockCopy(bytes, i, Date, 0, length); i += length;
                    UnixTime = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EventFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
                bytes[i++] = (byte)Date.Length;
                Buffer.BlockCopy(Date, 0, bytes, i, Date.Length); i += Date.Length;
                Utils.UIntToBytes(UnixTime, bytes, i); i += 4;
                Utils.UIntToBytes(EventFlags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class StatusDataBlock : PacketBlock
        {
            public uint Status;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public StatusDataBlock() { }
            public StatusDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Status = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Status, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                length += QueryData.Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                for (int j = 0; j < StatusData.Length; j++)
                    length += StatusData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;
        public QueryRepliesBlock[] QueryReplies;
        public StatusDataBlock[] StatusData;

        public DirEventsReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirEventsReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 37;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
            QueryReplies = null;
            StatusData = null;
        }

        public DirEventsReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(StatusData == null || StatusData.Length != -1) {
                StatusData = new StatusDataBlock[count];
                for(int j = 0; j < count; j++)
                { StatusData[j] = new StatusDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { StatusData[j].FromBytes(bytes, ref i); }
        }

        public DirEventsReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(StatusData == null || StatusData.Length != count) {
                StatusData = new StatusDataBlock[count];
                for(int j = 0; j < count; j++)
                { StatusData[j] = new StatusDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { StatusData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            length++;
            for (int j = 0; j < StatusData.Length; j++) { length += StatusData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)StatusData.Length;
            for (int j = 0; j < StatusData.Length; j++) { StatusData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += QueryData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            QueryData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int QueryRepliesStart = 0;
            int StatusDataStart = 0;
            do
            {
                int variableLength = 0;
                int QueryRepliesCount = 0;
                int StatusDataCount = 0;

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                i = StatusDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < StatusData.Length) {
                    int blockLength = StatusData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++StatusDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                packet[length++] = (byte)StatusDataCount;
                for (i = StatusDataStart; i < StatusDataStart + StatusDataCount; i++) { StatusData[i].ToBytes(packet, ref length); }
                StatusDataStart += StatusDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryRepliesStart < QueryReplies.Length ||
                StatusDataStart < StatusData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DirGroupsReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID GroupID;
            public byte[] GroupName;
            public int Members;
            public float SearchOrder;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (GroupName != null) { length += GroupName.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    GroupName = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupName, 0, length); i += length;
                    Members = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SearchOrder = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)GroupName.Length;
                Buffer.BlockCopy(GroupName, 0, bytes, i, GroupName.Length); i += GroupName.Length;
                Utils.IntToBytes(Members, bytes, i); i += 4;
                Utils.FloatToBytes(SearchOrder, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += QueryData.Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;
        public QueryRepliesBlock[] QueryReplies;

        public DirGroupsReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirGroupsReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 38;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
            QueryReplies = null;
        }

        public DirGroupsReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public DirGroupsReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += QueryData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            QueryData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int QueryRepliesStart = 0;
            do
            {
                int variableLength = 0;
                int QueryRepliesCount = 0;

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryRepliesStart < QueryReplies.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DirClassifiedQueryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;
            public byte[] QueryText;
            public uint QueryFlags;
            public uint Category;
            public int QueryStart;

            public override int Length
            {
                get
                {
                    int length = 29;
                    if (QueryText != null) { length += QueryText.Length; }
                    return length;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    QueryText = new byte[length];
                    Buffer.BlockCopy(bytes, i, QueryText, 0, length); i += length;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Category = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    QueryStart = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)QueryText.Length;
                Buffer.BlockCopy(QueryText, 0, bytes, i, QueryText.Length); i += QueryText.Length;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
                Utils.UIntToBytes(Category, bytes, i); i += 4;
                Utils.IntToBytes(QueryStart, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;

        public DirClassifiedQueryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DirClassifiedQuery;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 39;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
        }

        public DirClassifiedQueryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public DirClassifiedQueryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DirClassifiedReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID ClassifiedID;
            public byte[] Name;
            public byte ClassifiedFlags;
            public uint CreationDate;
            public uint ExpirationDate;
            public int PriceForListing;

            public override int Length
            {
                get
                {
                    int length = 30;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    ClassifiedFlags = (byte)bytes[i++];
                    CreationDate = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ExpirationDate = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PriceForListing = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = ClassifiedFlags;
                Utils.UIntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(ExpirationDate, bytes, i); i += 4;
                Utils.IntToBytes(PriceForListing, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class StatusDataBlock : PacketBlock
        {
            public uint Status;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public StatusDataBlock() { }
            public StatusDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Status = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Status, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                length += QueryData.Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                for (int j = 0; j < StatusData.Length; j++)
                    length += StatusData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;
        public QueryRepliesBlock[] QueryReplies;
        public StatusDataBlock[] StatusData;

        public DirClassifiedReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirClassifiedReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 41;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
            QueryReplies = null;
            StatusData = null;
        }

        public DirClassifiedReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(StatusData == null || StatusData.Length != -1) {
                StatusData = new StatusDataBlock[count];
                for(int j = 0; j < count; j++)
                { StatusData[j] = new StatusDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { StatusData[j].FromBytes(bytes, ref i); }
        }

        public DirClassifiedReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(StatusData == null || StatusData.Length != count) {
                StatusData = new StatusDataBlock[count];
                for(int j = 0; j < count; j++)
                { StatusData[j] = new StatusDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { StatusData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            length++;
            for (int j = 0; j < StatusData.Length; j++) { length += StatusData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)StatusData.Length;
            for (int j = 0; j < StatusData.Length; j++) { StatusData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += QueryData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            QueryData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int QueryRepliesStart = 0;
            int StatusDataStart = 0;
            do
            {
                int variableLength = 0;
                int QueryRepliesCount = 0;
                int StatusDataCount = 0;

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                i = StatusDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < StatusData.Length) {
                    int blockLength = StatusData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++StatusDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                packet[length++] = (byte)StatusDataCount;
                for (i = StatusDataStart; i < StatusDataStart + StatusDataCount; i++) { StatusData[i].ToBytes(packet, ref length); }
                StatusDataStart += StatusDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryRepliesStart < QueryReplies.Length ||
                StatusDataStart < StatusData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AvatarClassifiedReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID TargetID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    TargetID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                TargetID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ClassifiedID;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;

        public AvatarClassifiedReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AvatarClassifiedReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 42;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
        }

        public AvatarClassifiedReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public AvatarClassifiedReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ClassifiedInfoRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ClassifiedID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ClassifiedInfoRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ClassifiedInfoRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 43;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ClassifiedInfoRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ClassifiedInfoRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ClassifiedInfoReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ClassifiedID;
            public UUID CreatorID;
            public uint CreationDate;
            public uint ExpirationDate;
            public uint Category;
            public byte[] Name;
            public byte[] Desc;
            public UUID ParcelID;
            public uint ParentEstate;
            public UUID SnapshotID;
            public byte[] SimName;
            public Vector3d PosGlobal;
            public byte[] ParcelName;
            public byte ClassifiedFlags;
            public int PriceForListing;

            public override int Length
            {
                get
                {
                    int length = 114;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    if (ParcelName != null) { length += ParcelName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    CreationDate = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ExpirationDate = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Category = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    ParcelID.FromBytes(bytes, i); i += 16;
                    ParentEstate = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    PosGlobal.FromBytes(bytes, i); i += 24;
                    length = bytes[i++];
                    ParcelName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ParcelName, 0, length); i += length;
                    ClassifiedFlags = (byte)bytes[i++];
                    PriceForListing = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(ExpirationDate, bytes, i); i += 4;
                Utils.UIntToBytes(Category, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)(Desc.Length % 256);
                bytes[i++] = (byte)((Desc.Length >> 8) % 256);
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                ParcelID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(ParentEstate, bytes, i); i += 4;
                SnapshotID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                PosGlobal.ToBytes(bytes, i); i += 24;
                bytes[i++] = (byte)ParcelName.Length;
                Buffer.BlockCopy(ParcelName, 0, bytes, i, ParcelName.Length); i += ParcelName.Length;
                bytes[i++] = ClassifiedFlags;
                Utils.IntToBytes(PriceForListing, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ClassifiedInfoReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ClassifiedInfoReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 44;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ClassifiedInfoReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ClassifiedInfoReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ClassifiedInfoUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ClassifiedID;
            public uint Category;
            public byte[] Name;
            public byte[] Desc;
            public UUID ParcelID;
            public uint ParentEstate;
            public UUID SnapshotID;
            public Vector3d PosGlobal;
            public byte ClassifiedFlags;
            public int PriceForListing;

            public override int Length
            {
                get
                {
                    int length = 88;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                    Category = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    ParcelID.FromBytes(bytes, i); i += 16;
                    ParentEstate = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    PosGlobal.FromBytes(bytes, i); i += 24;
                    ClassifiedFlags = (byte)bytes[i++];
                    PriceForListing = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Category, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)(Desc.Length % 256);
                bytes[i++] = (byte)((Desc.Length >> 8) % 256);
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                ParcelID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(ParentEstate, bytes, i); i += 4;
                SnapshotID.ToBytes(bytes, i); i += 16;
                PosGlobal.ToBytes(bytes, i); i += 24;
                bytes[i++] = ClassifiedFlags;
                Utils.IntToBytes(PriceForListing, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ClassifiedInfoUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ClassifiedInfoUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 45;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ClassifiedInfoUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ClassifiedInfoUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ClassifiedDeletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ClassifiedID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ClassifiedDeletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ClassifiedDelete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 46;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ClassifiedDeletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ClassifiedDeletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ClassifiedGodDeletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ClassifiedID;
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ClassifiedID.FromBytes(bytes, i); i += 16;
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ClassifiedID.ToBytes(bytes, i); i += 16;
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ClassifiedGodDeletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ClassifiedGodDelete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 47;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ClassifiedGodDeletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ClassifiedGodDeletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DirLandQueryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;
            public uint QueryFlags;
            public uint SearchType;
            public int Price;
            public int Area;
            public int QueryStart;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SearchType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Price = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Area = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    QueryStart = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
                Utils.UIntToBytes(SearchType, bytes, i); i += 4;
                Utils.IntToBytes(Price, bytes, i); i += 4;
                Utils.IntToBytes(Area, bytes, i); i += 4;
                Utils.IntToBytes(QueryStart, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;

        public DirLandQueryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DirLandQuery;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 48;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
        }

        public DirLandQueryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public DirLandQueryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DirLandReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID ParcelID;
            public byte[] Name;
            public bool Auction;
            public bool ForSale;
            public int SalePrice;
            public int ActualArea;

            public override int Length
            {
                get
                {
                    int length = 27;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ParcelID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    Auction = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ForSale = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ActualArea = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ParcelID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)((Auction) ? 1 : 0);
                bytes[i++] = (byte)((ForSale) ? 1 : 0);
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                Utils.IntToBytes(ActualArea, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += QueryData.Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;
        public QueryRepliesBlock[] QueryReplies;

        public DirLandReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirLandReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 50;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
            QueryReplies = null;
        }

        public DirLandReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public DirLandReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += QueryData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            QueryData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int QueryRepliesStart = 0;
            do
            {
                int variableLength = 0;
                int QueryRepliesCount = 0;

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryRepliesStart < QueryReplies.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DirPopularQueryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;
            public uint QueryFlags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;

        public DirPopularQueryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DirPopularQuery;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 51;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
        }

        public DirPopularQueryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public DirPopularQueryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DirPopularReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class QueryRepliesBlock : PacketBlock
        {
            public UUID ParcelID;
            public byte[] Name;
            public float Dwell;

            public override int Length
            {
                get
                {
                    int length = 21;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public QueryRepliesBlock() { }
            public QueryRepliesBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ParcelID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    Dwell = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ParcelID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                Utils.FloatToBytes(Dwell, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += QueryData.Length;
                for (int j = 0; j < QueryReplies.Length; j++)
                    length += QueryReplies[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public QueryDataBlock QueryData;
        public QueryRepliesBlock[] QueryReplies;

        public DirPopularReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DirPopularReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 53;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            QueryData = new QueryDataBlock();
            QueryReplies = null;
        }

        public DirPopularReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != -1) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public DirPopularReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(QueryReplies == null || QueryReplies.Length != count) {
                QueryReplies = new QueryRepliesBlock[count];
                for(int j = 0; j < count; j++)
                { QueryReplies[j] = new QueryRepliesBlock(); }
            }
            for (int j = 0; j < count; j++)
            { QueryReplies[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += QueryData.Length;
            length++;
            for (int j = 0; j < QueryReplies.Length; j++) { length += QueryReplies[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)QueryReplies.Length;
            for (int j = 0; j < QueryReplies.Length; j++) { QueryReplies[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += QueryData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            QueryData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int QueryRepliesStart = 0;
            do
            {
                int variableLength = 0;
                int QueryRepliesCount = 0;

                i = QueryRepliesStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < QueryReplies.Length) {
                    int blockLength = QueryReplies[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++QueryRepliesCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)QueryRepliesCount;
                for (i = QueryRepliesStart; i < QueryRepliesStart + QueryRepliesCount; i++) { QueryReplies[i].ToBytes(packet, ref length); }
                QueryRepliesStart += QueryRepliesCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                QueryRepliesStart < QueryReplies.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelInfoRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ParcelID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ParcelID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ParcelID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelInfoRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelInfoRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 54;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelInfoRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelInfoRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelInfoReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ParcelID;
            public UUID OwnerID;
            public byte[] Name;
            public byte[] Desc;
            public int ActualArea;
            public int BillableArea;
            public byte Flags;
            public float GlobalX;
            public float GlobalY;
            public float GlobalZ;
            public byte[] SimName;
            public UUID SnapshotID;
            public float Dwell;
            public int SalePrice;
            public int AuctionID;

            public override int Length
            {
                get
                {
                    int length = 84;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ParcelID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    ActualArea = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    BillableArea = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (byte)bytes[i++];
                    GlobalX = Utils.BytesToFloat(bytes, i); i += 4;
                    GlobalY = Utils.BytesToFloat(bytes, i); i += 4;
                    GlobalZ = Utils.BytesToFloat(bytes, i); i += 4;
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    Dwell = Utils.BytesToFloat(bytes, i); i += 4;
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AuctionID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ParcelID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Desc.Length;
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                Utils.IntToBytes(ActualArea, bytes, i); i += 4;
                Utils.IntToBytes(BillableArea, bytes, i); i += 4;
                bytes[i++] = Flags;
                Utils.FloatToBytes(GlobalX, bytes, i); i += 4;
                Utils.FloatToBytes(GlobalY, bytes, i); i += 4;
                Utils.FloatToBytes(GlobalZ, bytes, i); i += 4;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                SnapshotID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(Dwell, bytes, i); i += 4;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                Utils.IntToBytes(AuctionID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelInfoReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelInfoReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 55;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelInfoReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelInfoReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelObjectOwnersRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelObjectOwnersRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelObjectOwnersRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 56;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelObjectOwnersRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelObjectOwnersRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelObjectOwnersReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID OwnerID;
            public bool IsGroupOwned;
            public int Count;
            public bool OnlineStatus;

            public override int Length
            {
                get
                {
                    return 22;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                    IsGroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Count = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OnlineStatus = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsGroupOwned) ? 1 : 0);
                Utils.IntToBytes(Count, bytes, i); i += 4;
                bytes[i++] = (byte)((OnlineStatus) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public DataBlock[] Data;

        public ParcelObjectOwnersReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelObjectOwnersReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 57;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Data = null;
        }

        public ParcelObjectOwnersReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public ParcelObjectOwnersReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupNoticesListRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public GroupNoticesListRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupNoticesListRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 58;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public GroupNoticesListRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public GroupNoticesListRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupNoticesListReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID NoticeID;
            public uint Timestamp;
            public byte[] FromName;
            public byte[] Subject;
            public bool HasAttachment;
            public byte AssetType;

            public override int Length
            {
                get
                {
                    int length = 26;
                    if (FromName != null) { length += FromName.Length; }
                    if (Subject != null) { length += Subject.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    NoticeID.FromBytes(bytes, i); i += 16;
                    Timestamp = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    FromName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FromName, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Subject = new byte[length];
                    Buffer.BlockCopy(bytes, i, Subject, 0, length); i += length;
                    HasAttachment = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AssetType = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                NoticeID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Timestamp, bytes, i); i += 4;
                bytes[i++] = (byte)(FromName.Length % 256);
                bytes[i++] = (byte)((FromName.Length >> 8) % 256);
                Buffer.BlockCopy(FromName, 0, bytes, i, FromName.Length); i += FromName.Length;
                bytes[i++] = (byte)(Subject.Length % 256);
                bytes[i++] = (byte)((Subject.Length >> 8) % 256);
                Buffer.BlockCopy(Subject, 0, bytes, i, Subject.Length); i += Subject.Length;
                bytes[i++] = (byte)((HasAttachment) ? 1 : 0);
                bytes[i++] = AssetType;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;

        public GroupNoticesListReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupNoticesListReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 59;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
        }

        public GroupNoticesListReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public GroupNoticesListReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupNoticeRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupNoticeID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupNoticeID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupNoticeID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public GroupNoticeRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupNoticeRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 60;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public GroupNoticeRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public GroupNoticeRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID RegionID;
            public Vector3 Position;
            public Vector3 LookAt;

            public override int Length
            {
                get
                {
                    return 40;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionID.FromBytes(bytes, i); i += 16;
                    Position.FromBytes(bytes, i); i += 12;
                    LookAt.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RegionID.ToBytes(bytes, i); i += 16;
                Position.ToBytes(bytes, i); i += 12;
                LookAt.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Info.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InfoBlock Info;

        public TeleportRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 62;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Info = new InfoBlock();
        }

        public TeleportRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public TeleportRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportLocationRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public ulong RegionHandle;
            public Vector3 Position;
            public Vector3 LookAt;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Position.FromBytes(bytes, i); i += 12;
                    LookAt.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                Position.ToBytes(bytes, i); i += 12;
                LookAt.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Info.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InfoBlock Info;

        public TeleportLocationRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportLocationRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 63;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Info = new InfoBlock();
        }

        public TeleportLocationRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public TeleportLocationRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportLocalPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID AgentID;
            public uint LocationID;
            public Vector3 Position;
            public Vector3 LookAt;
            public uint TeleportFlags;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    LocationID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Position.FromBytes(bytes, i); i += 12;
                    LookAt.FromBytes(bytes, i); i += 12;
                    TeleportFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(LocationID, bytes, i); i += 4;
                Position.ToBytes(bytes, i); i += 12;
                LookAt.ToBytes(bytes, i); i += 12;
                Utils.UIntToBytes(TeleportFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public TeleportLocalPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportLocal;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 64;
            Header.Reliable = true;
            Info = new InfoBlock();
        }

        public TeleportLocalPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public TeleportLocalPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportLandmarkRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID LandmarkID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    LandmarkID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                LandmarkID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public TeleportLandmarkRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportLandmarkRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 65;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Info = new InfoBlock();
        }

        public TeleportLandmarkRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public TeleportLandmarkRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportProgressPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public uint TeleportFlags;
            public byte[] Message;

            public override int Length
            {
                get
                {
                    int length = 5;
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TeleportFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(TeleportFlags, bytes, i); i += 4;
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Info.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InfoBlock Info;

        public TeleportProgressPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportProgress;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 66;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Info = new InfoBlock();
        }

        public TeleportProgressPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public TeleportProgressPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportFinishPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID AgentID;
            public uint LocationID;
            public uint SimIP;
            public ushort SimPort;
            public ulong RegionHandle;
            public byte[] SeedCapability;
            public byte SimAccess;
            public uint TeleportFlags;

            public override int Length
            {
                get
                {
                    int length = 41;
                    if (SeedCapability != null) { length += SeedCapability.Length; }
                    return length;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    LocationID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SimIP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SimPort = (ushort)((bytes[i++] << 8) + bytes[i++]);
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    SeedCapability = new byte[length];
                    Buffer.BlockCopy(bytes, i, SeedCapability, 0, length); i += length;
                    SimAccess = (byte)bytes[i++];
                    TeleportFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(LocationID, bytes, i); i += 4;
                Utils.UIntToBytes(SimIP, bytes, i); i += 4;
                bytes[i++] = (byte)((SimPort >> 8) % 256);
                bytes[i++] = (byte)(SimPort % 256);
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = (byte)(SeedCapability.Length % 256);
                bytes[i++] = (byte)((SeedCapability.Length >> 8) % 256);
                Buffer.BlockCopy(SeedCapability, 0, bytes, i, SeedCapability.Length); i += SeedCapability.Length;
                bytes[i++] = SimAccess;
                Utils.UIntToBytes(TeleportFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public TeleportFinishPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportFinish;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 69;
            Header.Reliable = true;
            Info = new InfoBlock();
        }

        public TeleportFinishPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public TeleportFinishPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class StartLurePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public byte LureType;
            public byte[] Message;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    LureType = (byte)bytes[i++];
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = LureType;
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
            }

        }

        /// <exclude/>
        public sealed class TargetDataBlock : PacketBlock
        {
            public UUID TargetID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TargetDataBlock() { }
            public TargetDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += Info.Length;
                for (int j = 0; j < TargetData.Length; j++)
                    length += TargetData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InfoBlock Info;
        public TargetDataBlock[] TargetData;

        public StartLurePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.StartLure;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 70;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Info = new InfoBlock();
            TargetData = null;
        }

        public StartLurePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(TargetData == null || TargetData.Length != -1) {
                TargetData = new TargetDataBlock[count];
                for(int j = 0; j < count; j++)
                { TargetData[j] = new TargetDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { TargetData[j].FromBytes(bytes, ref i); }
        }

        public StartLurePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(TargetData == null || TargetData.Length != count) {
                TargetData = new TargetDataBlock[count];
                for(int j = 0; j < count; j++)
                { TargetData[j] = new TargetDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { TargetData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Info.Length;
            length++;
            for (int j = 0; j < TargetData.Length; j++) { length += TargetData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            bytes[i++] = (byte)TargetData.Length;
            for (int j = 0; j < TargetData.Length; j++) { TargetData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += Info.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            Info.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int TargetDataStart = 0;
            do
            {
                int variableLength = 0;
                int TargetDataCount = 0;

                i = TargetDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < TargetData.Length) {
                    int blockLength = TargetData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++TargetDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)TargetDataCount;
                for (i = TargetDataStart; i < TargetDataStart + TargetDataCount; i++) { TargetData[i].ToBytes(packet, ref length); }
                TargetDataStart += TargetDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                TargetDataStart < TargetData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class TeleportLureRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID LureID;
            public uint TeleportFlags;

            public override int Length
            {
                get
                {
                    return 52;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    LureID.FromBytes(bytes, i); i += 16;
                    TeleportFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                LureID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(TeleportFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public TeleportLureRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportLureRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 71;
            Header.Reliable = true;
            Info = new InfoBlock();
        }

        public TeleportLureRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public TeleportLureRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportCancelPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public TeleportCancelPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportCancel;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 72;
            Header.Reliable = true;
            Info = new InfoBlock();
        }

        public TeleportCancelPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public TeleportCancelPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportStartPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public uint TeleportFlags;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TeleportFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(TeleportFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Info.Length;
                return length;
            }
        }
        public InfoBlock Info;

        public TeleportStartPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TeleportStart;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 73;
            Header.Reliable = true;
            Info = new InfoBlock();
        }

        public TeleportStartPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
        }

        public TeleportStartPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TeleportFailedPacket : Packet
    {
        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public UUID AgentID;
            public byte[] Reason;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Reason != null) { length += Reason.Length; }
                    return length;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Reason = new byte[length];
                    Buffer.BlockCopy(bytes, i, Reason, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Reason.Length;
                Buffer.BlockCopy(Reason, 0, bytes, i, Reason.Length); i += Reason.Length;
            }

        }

        /// <exclude/>
        public sealed class AlertInfoBlock : PacketBlock
        {
            public byte[] Message;
            public byte[] ExtraParams;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Message != null) { length += Message.Length; }
                    if (ExtraParams != null) { length += ExtraParams.Length; }
                    return length;
                }
            }

            public AlertInfoBlock() { }
            public AlertInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    length = bytes[i++];
                    ExtraParams = new byte[length];
                    Buffer.BlockCopy(bytes, i, ExtraParams, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                bytes[i++] = (byte)ExtraParams.Length;
                Buffer.BlockCopy(ExtraParams, 0, bytes, i, ExtraParams.Length); i += ExtraParams.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += Info.Length;
                for (int j = 0; j < AlertInfo.Length; j++)
                    length += AlertInfo[j].Length;
                return length;
            }
        }
        public InfoBlock Info;
        public AlertInfoBlock[] AlertInfo;

        public TeleportFailedPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.TeleportFailed;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 74;
            Header.Reliable = true;
            Info = new InfoBlock();
            AlertInfo = null;
        }

        public TeleportFailedPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Info.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AlertInfo == null || AlertInfo.Length != -1) {
                AlertInfo = new AlertInfoBlock[count];
                for(int j = 0; j < count; j++)
                { AlertInfo[j] = new AlertInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AlertInfo[j].FromBytes(bytes, ref i); }
        }

        public TeleportFailedPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Info.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AlertInfo == null || AlertInfo.Length != count) {
                AlertInfo = new AlertInfoBlock[count];
                for(int j = 0; j < count; j++)
                { AlertInfo[j] = new AlertInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AlertInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Info.Length;
            length++;
            for (int j = 0; j < AlertInfo.Length; j++) { length += AlertInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AlertInfo.Length;
            for (int j = 0; j < AlertInfo.Length; j++) { AlertInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += Info.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            Info.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int AlertInfoStart = 0;
            do
            {
                int variableLength = 0;
                int AlertInfoCount = 0;

                i = AlertInfoStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AlertInfo.Length) {
                    int blockLength = AlertInfo[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AlertInfoCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AlertInfoCount;
                for (i = AlertInfoStart; i < AlertInfoStart + AlertInfoCount; i++) { AlertInfo[i].ToBytes(packet, ref length); }
                AlertInfoStart += AlertInfoCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AlertInfoStart < AlertInfo.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UndoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public UndoPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.Undo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 75;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public UndoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public UndoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RedoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public RedoPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.Redo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 76;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public RedoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public RedoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UndoLandPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public UndoLandPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UndoLand;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 77;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public UndoLandPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public UndoLandPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentPausePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint SerialNum;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    SerialNum = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(SerialNum, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentPausePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentPause;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 78;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public AgentPausePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentPausePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentResumePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint SerialNum;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    SerialNum = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(SerialNum, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentResumePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentResume;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 79;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public AgentResumePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentResumePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ChatFromViewerPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ChatDataBlock : PacketBlock
        {
            public byte[] Message;
            public byte Type;
            public int Channel;

            public override int Length
            {
                get
                {
                    int length = 7;
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public ChatDataBlock() { }
            public ChatDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    Type = (byte)bytes[i++];
                    Channel = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(Message.Length % 256);
                bytes[i++] = (byte)((Message.Length >> 8) % 256);
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                bytes[i++] = Type;
                Utils.IntToBytes(Channel, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ChatData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ChatDataBlock ChatData;

        public ChatFromViewerPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ChatFromViewer;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 80;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ChatData = new ChatDataBlock();
        }

        public ChatFromViewerPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ChatData.FromBytes(bytes, ref i);
        }

        public ChatFromViewerPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ChatData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ChatData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ChatData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentThrottlePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint CircuitCode;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    CircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CircuitCode, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ThrottleBlock : PacketBlock
        {
            public uint GenCounter;
            public byte[] Throttles;

            public override int Length
            {
                get
                {
                    int length = 5;
                    if (Throttles != null) { length += Throttles.Length; }
                    return length;
                }
            }

            public ThrottleBlock() { }
            public ThrottleBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GenCounter = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Throttles = new byte[length];
                    Buffer.BlockCopy(bytes, i, Throttles, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(GenCounter, bytes, i); i += 4;
                bytes[i++] = (byte)Throttles.Length;
                Buffer.BlockCopy(Throttles, 0, bytes, i, Throttles.Length); i += Throttles.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Throttle.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ThrottleBlock Throttle;

        public AgentThrottlePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentThrottle;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 81;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Throttle = new ThrottleBlock();
        }

        public AgentThrottlePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Throttle.FromBytes(bytes, ref i);
        }

        public AgentThrottlePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Throttle.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Throttle.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Throttle.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentFOVPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint CircuitCode;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    CircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CircuitCode, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class FOVBlockBlock : PacketBlock
        {
            public uint GenCounter;
            public float VerticalAngle;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public FOVBlockBlock() { }
            public FOVBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GenCounter = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    VerticalAngle = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(GenCounter, bytes, i); i += 4;
                Utils.FloatToBytes(VerticalAngle, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += FOVBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FOVBlockBlock FOVBlock;

        public AgentFOVPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentFOV;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 82;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FOVBlock = new FOVBlockBlock();
        }

        public AgentFOVPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            FOVBlock.FromBytes(bytes, ref i);
        }

        public AgentFOVPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            FOVBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += FOVBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            FOVBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentHeightWidthPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint CircuitCode;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    CircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CircuitCode, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class HeightWidthBlockBlock : PacketBlock
        {
            public uint GenCounter;
            public ushort Height;
            public ushort Width;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public HeightWidthBlockBlock() { }
            public HeightWidthBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GenCounter = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Height = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    Width = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(GenCounter, bytes, i); i += 4;
                bytes[i++] = (byte)(Height % 256);
                bytes[i++] = (byte)((Height >> 8) % 256);
                bytes[i++] = (byte)(Width % 256);
                bytes[i++] = (byte)((Width >> 8) % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += HeightWidthBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public HeightWidthBlockBlock HeightWidthBlock;

        public AgentHeightWidthPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentHeightWidth;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 83;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            HeightWidthBlock = new HeightWidthBlockBlock();
        }

        public AgentHeightWidthPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            HeightWidthBlock.FromBytes(bytes, ref i);
        }

        public AgentHeightWidthPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            HeightWidthBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += HeightWidthBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            HeightWidthBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentSetAppearancePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint SerialNum;
            public Vector3 Size;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    SerialNum = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Size.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(SerialNum, bytes, i); i += 4;
                Size.ToBytes(bytes, i); i += 12;
            }

        }

        /// <exclude/>
        public sealed class WearableDataBlock : PacketBlock
        {
            public UUID CacheID;
            public byte TextureIndex;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public WearableDataBlock() { }
            public WearableDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    CacheID.FromBytes(bytes, i); i += 16;
                    TextureIndex = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                CacheID.ToBytes(bytes, i); i += 16;
                bytes[i++] = TextureIndex;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public byte[] TextureEntry;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (TextureEntry != null) { length += TextureEntry.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    TextureEntry = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureEntry, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(TextureEntry.Length % 256);
                bytes[i++] = (byte)((TextureEntry.Length >> 8) % 256);
                Buffer.BlockCopy(TextureEntry, 0, bytes, i, TextureEntry.Length); i += TextureEntry.Length;
            }

        }

        /// <exclude/>
        public sealed class VisualParamBlock : PacketBlock
        {
            public byte ParamValue;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public VisualParamBlock() { }
            public VisualParamBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ParamValue = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = ParamValue;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                for (int j = 0; j < WearableData.Length; j++)
                    length += WearableData[j].Length;
                length += ObjectData.Length;
                for (int j = 0; j < VisualParam.Length; j++)
                    length += VisualParam[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public WearableDataBlock[] WearableData;
        public ObjectDataBlock ObjectData;
        public VisualParamBlock[] VisualParam;

        public AgentSetAppearancePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentSetAppearance;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 84;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            WearableData = null;
            ObjectData = new ObjectDataBlock();
            VisualParam = null;
        }

        public AgentSetAppearancePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != -1) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
            ObjectData.FromBytes(bytes, ref i);
            count = (int)bytes[i++];
            if(VisualParam == null || VisualParam.Length != -1) {
                VisualParam = new VisualParamBlock[count];
                for(int j = 0; j < count; j++)
                { VisualParam[j] = new VisualParamBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VisualParam[j].FromBytes(bytes, ref i); }
        }

        public AgentSetAppearancePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != count) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
            ObjectData.FromBytes(bytes, ref i);
            count = (int)bytes[i++];
            if(VisualParam == null || VisualParam.Length != count) {
                VisualParam = new VisualParamBlock[count];
                for(int j = 0; j < count; j++)
                { VisualParam[j] = new VisualParamBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VisualParam[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < WearableData.Length; j++) { length += WearableData[j].Length; }
            length++;
            for (int j = 0; j < VisualParam.Length; j++) { length += VisualParam[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)WearableData.Length;
            for (int j = 0; j < WearableData.Length; j++) { WearableData[j].ToBytes(bytes, ref i); }
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)VisualParam.Length;
            for (int j = 0; j < VisualParam.Length; j++) { VisualParam[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentQuitCopyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FuseBlockBlock : PacketBlock
        {
            public uint ViewerCircuitCode;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public FuseBlockBlock() { }
            public FuseBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ViewerCircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ViewerCircuitCode, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += FuseBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FuseBlockBlock FuseBlock;

        public AgentQuitCopyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentQuitCopy;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 85;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FuseBlock = new FuseBlockBlock();
        }

        public AgentQuitCopyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            FuseBlock.FromBytes(bytes, ref i);
        }

        public AgentQuitCopyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            FuseBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += FuseBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            FuseBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ImageNotInDatabasePacket : Packet
    {
        /// <exclude/>
        public sealed class ImageIDBlock : PacketBlock
        {
            public UUID ID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ImageIDBlock() { }
            public ImageIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ImageID.Length;
                return length;
            }
        }
        public ImageIDBlock ImageID;

        public ImageNotInDatabasePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ImageNotInDatabase;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 86;
            Header.Reliable = true;
            ImageID = new ImageIDBlock();
        }

        public ImageNotInDatabasePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ImageID.FromBytes(bytes, ref i);
        }

        public ImageNotInDatabasePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ImageID.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ImageID.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ImageID.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RebakeAvatarTexturesPacket : Packet
    {
        /// <exclude/>
        public sealed class TextureDataBlock : PacketBlock
        {
            public UUID TextureID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TextureDataBlock() { }
            public TextureDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TextureID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TextureID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TextureData.Length;
                return length;
            }
        }
        public TextureDataBlock TextureData;

        public RebakeAvatarTexturesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RebakeAvatarTextures;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 87;
            Header.Reliable = true;
            TextureData = new TextureDataBlock();
        }

        public RebakeAvatarTexturesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TextureData.FromBytes(bytes, ref i);
        }

        public RebakeAvatarTexturesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TextureData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TextureData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TextureData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SetAlwaysRunPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public bool AlwaysRun;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    AlwaysRun = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((AlwaysRun) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public SetAlwaysRunPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SetAlwaysRun;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 88;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public SetAlwaysRunPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public SetAlwaysRunPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectDeletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public bool Force;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Force = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Force) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDeletePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDelete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 89;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDeletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDeletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDuplicatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class SharedDataBlock : PacketBlock
        {
            public Vector3 Offset;
            public uint DuplicateFlags;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public SharedDataBlock() { }
            public SharedDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Offset.FromBytes(bytes, i); i += 12;
                    DuplicateFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Offset.ToBytes(bytes, i); i += 12;
                Utils.UIntToBytes(DuplicateFlags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += SharedData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public SharedDataBlock SharedData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDuplicatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDuplicate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 90;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            SharedData = new SharedDataBlock();
            ObjectData = null;
        }

        public ObjectDuplicatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            SharedData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDuplicatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            SharedData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += SharedData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            SharedData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += SharedData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            SharedData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDuplicateOnRayPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;
            public Vector3 RayStart;
            public Vector3 RayEnd;
            public bool BypassRaycast;
            public bool RayEndIsIntersection;
            public bool CopyCenters;
            public bool CopyRotates;
            public UUID RayTargetID;
            public uint DuplicateFlags;

            public override int Length
            {
                get
                {
                    return 96;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    RayStart.FromBytes(bytes, i); i += 12;
                    RayEnd.FromBytes(bytes, i); i += 12;
                    BypassRaycast = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RayEndIsIntersection = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    CopyCenters = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    CopyRotates = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RayTargetID.FromBytes(bytes, i); i += 16;
                    DuplicateFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                RayStart.ToBytes(bytes, i); i += 12;
                RayEnd.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)((BypassRaycast) ? 1 : 0);
                bytes[i++] = (byte)((RayEndIsIntersection) ? 1 : 0);
                bytes[i++] = (byte)((CopyCenters) ? 1 : 0);
                bytes[i++] = (byte)((CopyRotates) ? 1 : 0);
                RayTargetID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(DuplicateFlags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDuplicateOnRayPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDuplicateOnRay;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 91;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDuplicateOnRayPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDuplicateOnRayPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectScalePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public Vector3 Scale;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Scale.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                Scale.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectScalePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectScale;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 92;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectScalePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectScalePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectRotationPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public Quaternion Rotation;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Rotation.FromBytes(bytes, i, true); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                Rotation.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectRotationPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectRotation;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 93;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectRotationPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectRotationPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectFlagUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint ObjectLocalID;
            public bool UsePhysics;
            public bool IsTemporary;
            public bool IsPhantom;
            public bool CastsShadows;

            public override int Length
            {
                get
                {
                    return 40;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    UsePhysics = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    IsTemporary = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    IsPhantom = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    CastsShadows = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = (byte)((UsePhysics) ? 1 : 0);
                bytes[i++] = (byte)((IsTemporary) ? 1 : 0);
                bytes[i++] = (byte)((IsPhantom) ? 1 : 0);
                bytes[i++] = (byte)((CastsShadows) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ExtraPhysicsBlock : PacketBlock
        {
            public byte PhysicsShapeType;
            public float Density;
            public float Friction;
            public float Restitution;
            public float GravityMultiplier;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public ExtraPhysicsBlock() { }
            public ExtraPhysicsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PhysicsShapeType = (byte)bytes[i++];
                    Density = Utils.BytesToFloat(bytes, i); i += 4;
                    Friction = Utils.BytesToFloat(bytes, i); i += 4;
                    Restitution = Utils.BytesToFloat(bytes, i); i += 4;
                    GravityMultiplier = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = PhysicsShapeType;
                Utils.FloatToBytes(Density, bytes, i); i += 4;
                Utils.FloatToBytes(Friction, bytes, i); i += 4;
                Utils.FloatToBytes(Restitution, bytes, i); i += 4;
                Utils.FloatToBytes(GravityMultiplier, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ExtraPhysics.Length; j++)
                    length += ExtraPhysics[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ExtraPhysicsBlock[] ExtraPhysics;

        public ObjectFlagUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectFlagUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 94;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ExtraPhysics = null;
        }

        public ObjectFlagUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ExtraPhysics == null || ExtraPhysics.Length != -1) {
                ExtraPhysics = new ExtraPhysicsBlock[count];
                for(int j = 0; j < count; j++)
                { ExtraPhysics[j] = new ExtraPhysicsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ExtraPhysics[j].FromBytes(bytes, ref i); }
        }

        public ObjectFlagUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ExtraPhysics == null || ExtraPhysics.Length != count) {
                ExtraPhysics = new ExtraPhysicsBlock[count];
                for(int j = 0; j < count; j++)
                { ExtraPhysics[j] = new ExtraPhysicsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ExtraPhysics[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ExtraPhysics.Length; j++) { length += ExtraPhysics[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ExtraPhysics.Length;
            for (int j = 0; j < ExtraPhysics.Length; j++) { ExtraPhysics[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ExtraPhysicsStart = 0;
            do
            {
                int variableLength = 0;
                int ExtraPhysicsCount = 0;

                i = ExtraPhysicsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ExtraPhysics.Length) {
                    int blockLength = ExtraPhysics[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ExtraPhysicsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ExtraPhysicsCount;
                for (i = ExtraPhysicsStart; i < ExtraPhysicsStart + ExtraPhysicsCount; i++) { ExtraPhysics[i].ToBytes(packet, ref length); }
                ExtraPhysicsStart += ExtraPhysicsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ExtraPhysicsStart < ExtraPhysics.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectClickActionPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte ClickAction;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ClickAction = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = ClickAction;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectClickActionPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectClickAction;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 95;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectClickActionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectClickActionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectImagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte[] MediaURL;
            public byte[] TextureEntry;

            public override int Length
            {
                get
                {
                    int length = 7;
                    if (MediaURL != null) { length += MediaURL.Length; }
                    if (TextureEntry != null) { length += TextureEntry.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    MediaURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaURL, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    TextureEntry = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureEntry, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = (byte)MediaURL.Length;
                Buffer.BlockCopy(MediaURL, 0, bytes, i, MediaURL.Length); i += MediaURL.Length;
                bytes[i++] = (byte)(TextureEntry.Length % 256);
                bytes[i++] = (byte)((TextureEntry.Length >> 8) % 256);
                Buffer.BlockCopy(TextureEntry, 0, bytes, i, TextureEntry.Length); i += TextureEntry.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectImagePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectImage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 96;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectImagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectImagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectMaterialPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte Material;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Material = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = Material;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectMaterialPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectMaterial;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 97;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectMaterialPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectMaterialPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectShapePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte PathCurve;
            public byte ProfileCurve;
            public ushort PathBegin;
            public ushort PathEnd;
            public byte PathScaleX;
            public byte PathScaleY;
            public byte PathShearX;
            public byte PathShearY;
            public sbyte PathTwist;
            public sbyte PathTwistBegin;
            public sbyte PathRadiusOffset;
            public sbyte PathTaperX;
            public sbyte PathTaperY;
            public byte PathRevolutions;
            public sbyte PathSkew;
            public ushort ProfileBegin;
            public ushort ProfileEnd;
            public ushort ProfileHollow;

            public override int Length
            {
                get
                {
                    return 27;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PathCurve = (byte)bytes[i++];
                    ProfileCurve = (byte)bytes[i++];
                    PathBegin = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    PathEnd = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    PathScaleX = (byte)bytes[i++];
                    PathScaleY = (byte)bytes[i++];
                    PathShearX = (byte)bytes[i++];
                    PathShearY = (byte)bytes[i++];
                    PathTwist = (sbyte)bytes[i++];
                    PathTwistBegin = (sbyte)bytes[i++];
                    PathRadiusOffset = (sbyte)bytes[i++];
                    PathTaperX = (sbyte)bytes[i++];
                    PathTaperY = (sbyte)bytes[i++];
                    PathRevolutions = (byte)bytes[i++];
                    PathSkew = (sbyte)bytes[i++];
                    ProfileBegin = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ProfileEnd = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ProfileHollow = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = PathCurve;
                bytes[i++] = ProfileCurve;
                bytes[i++] = (byte)(PathBegin % 256);
                bytes[i++] = (byte)((PathBegin >> 8) % 256);
                bytes[i++] = (byte)(PathEnd % 256);
                bytes[i++] = (byte)((PathEnd >> 8) % 256);
                bytes[i++] = PathScaleX;
                bytes[i++] = PathScaleY;
                bytes[i++] = PathShearX;
                bytes[i++] = PathShearY;
                bytes[i++] = (byte)PathTwist;
                bytes[i++] = (byte)PathTwistBegin;
                bytes[i++] = (byte)PathRadiusOffset;
                bytes[i++] = (byte)PathTaperX;
                bytes[i++] = (byte)PathTaperY;
                bytes[i++] = PathRevolutions;
                bytes[i++] = (byte)PathSkew;
                bytes[i++] = (byte)(ProfileBegin % 256);
                bytes[i++] = (byte)((ProfileBegin >> 8) % 256);
                bytes[i++] = (byte)(ProfileEnd % 256);
                bytes[i++] = (byte)((ProfileEnd >> 8) % 256);
                bytes[i++] = (byte)(ProfileHollow % 256);
                bytes[i++] = (byte)((ProfileHollow >> 8) % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectShapePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectShape;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 98;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectShapePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectShapePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectExtraParamsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public ushort ParamType;
            public bool ParamInUse;
            public uint ParamSize;
            public byte[] ParamData;

            public override int Length
            {
                get
                {
                    int length = 12;
                    if (ParamData != null) { length += ParamData.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParamType = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ParamInUse = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ParamSize = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ParamData = new byte[length];
                    Buffer.BlockCopy(bytes, i, ParamData, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = (byte)(ParamType % 256);
                bytes[i++] = (byte)((ParamType >> 8) % 256);
                bytes[i++] = (byte)((ParamInUse) ? 1 : 0);
                Utils.UIntToBytes(ParamSize, bytes, i); i += 4;
                bytes[i++] = (byte)ParamData.Length;
                Buffer.BlockCopy(ParamData, 0, bytes, i, ParamData.Length); i += ParamData.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectExtraParamsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectExtraParams;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 99;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectExtraParamsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectExtraParamsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectOwnerPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class HeaderDataBlock : PacketBlock
        {
            public bool Override;
            public UUID OwnerID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public HeaderDataBlock() { }
            public HeaderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Override = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((Override) ? 1 : 0);
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += HeaderData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public HeaderDataBlock HeaderData;
        public ObjectDataBlock[] ObjectData;

        public ObjectOwnerPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectOwner;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 100;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            HeaderData = new HeaderDataBlock();
            ObjectData = null;
        }

        public ObjectOwnerPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectOwnerPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += HeaderData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            HeaderData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += HeaderData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            HeaderData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectGroupPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectGroupPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectGroup;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 101;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectGroupPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectGroupPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectBuyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;
            public UUID CategoryID;

            public override int Length
            {
                get
                {
                    return 64;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    CategoryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                CategoryID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte SaleType;
            public int SalePrice;

            public override int Length
            {
                get
                {
                    return 9;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectBuyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectBuy;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 102;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectBuyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectBuyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class BuyObjectInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID ItemID;
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public BuyObjectInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.BuyObjectInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 103;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public BuyObjectInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public BuyObjectInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DerezContainerPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ObjectID;
            public bool Delete;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    Delete = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Delete) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Data.Length;
                return length;
            }
        }
        public DataBlock Data;

        public DerezContainerPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DerezContainer;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 104;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Data = new DataBlock();
        }

        public DerezContainerPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
        }

        public DerezContainerPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectPermissionsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class HeaderDataBlock : PacketBlock
        {
            public bool Override;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public HeaderDataBlock() { }
            public HeaderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Override = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((Override) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte Field;
            public byte Set;
            public uint Mask;

            public override int Length
            {
                get
                {
                    return 10;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Field = (byte)bytes[i++];
                    Set = (byte)bytes[i++];
                    Mask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = Field;
                bytes[i++] = Set;
                Utils.UIntToBytes(Mask, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += HeaderData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public HeaderDataBlock HeaderData;
        public ObjectDataBlock[] ObjectData;

        public ObjectPermissionsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectPermissions;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 105;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            HeaderData = new HeaderDataBlock();
            ObjectData = null;
        }

        public ObjectPermissionsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectPermissionsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += HeaderData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            HeaderData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += HeaderData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            HeaderData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectSaleInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint LocalID;
            public byte SaleType;
            public int SalePrice;

            public override int Length
            {
                get
                {
                    return 9;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectSaleInfoPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectSaleInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 106;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectSaleInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectSaleInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectNamePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint LocalID;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 5;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectNamePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectName;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 107;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectNamePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectNamePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDescriptionPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint LocalID;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 5;
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDescriptionPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDescription;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 108;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDescriptionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDescriptionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectCategoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint LocalID;
            public uint Category;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Category = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                Utils.UIntToBytes(Category, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectCategoryPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectCategory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 109;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectCategoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectCategoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectSelectPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectSelectPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectSelect;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 110;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectSelectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectSelectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDeselectPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDeselectPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDeselect;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 111;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDeselectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDeselectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectAttachPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public byte AttachmentPoint;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    AttachmentPoint = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = AttachmentPoint;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public Quaternion Rotation;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Rotation.FromBytes(bytes, i, true); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                Rotation.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectAttachPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectAttach;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 112;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectAttachPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectAttachPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDetachPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDetachPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDetach;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 113;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDetachPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDetachPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDropPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDropPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDrop;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 114;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDropPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDropPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectLinkPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectLinkPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectLink;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 115;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectLinkPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectLinkPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDelinkPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectDelinkPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDelink;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 116;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectDelinkPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectDelinkPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectGrabPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint LocalID;
            public Vector3 GrabOffset;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GrabOffset.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                GrabOffset.ToBytes(bytes, i); i += 12;
            }

        }

        /// <exclude/>
        public sealed class SurfaceInfoBlock : PacketBlock
        {
            public Vector3 UVCoord;
            public Vector3 STCoord;
            public int FaceIndex;
            public Vector3 Position;
            public Vector3 Normal;
            public Vector3 Binormal;

            public override int Length
            {
                get
                {
                    return 64;
                }
            }

            public SurfaceInfoBlock() { }
            public SurfaceInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    UVCoord.FromBytes(bytes, i); i += 12;
                    STCoord.FromBytes(bytes, i); i += 12;
                    FaceIndex = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Position.FromBytes(bytes, i); i += 12;
                    Normal.FromBytes(bytes, i); i += 12;
                    Binormal.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                UVCoord.ToBytes(bytes, i); i += 12;
                STCoord.ToBytes(bytes, i); i += 12;
                Utils.IntToBytes(FaceIndex, bytes, i); i += 4;
                Position.ToBytes(bytes, i); i += 12;
                Normal.ToBytes(bytes, i); i += 12;
                Binormal.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += ObjectData.Length;
                for (int j = 0; j < SurfaceInfo.Length; j++)
                    length += SurfaceInfo[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;
        public SurfaceInfoBlock[] SurfaceInfo;

        public ObjectGrabPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectGrab;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 117;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
            SurfaceInfo = null;
        }

        public ObjectGrabPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SurfaceInfo == null || SurfaceInfo.Length != -1) {
                SurfaceInfo = new SurfaceInfoBlock[count];
                for(int j = 0; j < count; j++)
                { SurfaceInfo[j] = new SurfaceInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SurfaceInfo[j].FromBytes(bytes, ref i); }
        }

        public ObjectGrabPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SurfaceInfo == null || SurfaceInfo.Length != count) {
                SurfaceInfo = new SurfaceInfoBlock[count];
                for(int j = 0; j < count; j++)
                { SurfaceInfo[j] = new SurfaceInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SurfaceInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < SurfaceInfo.Length; j++) { length += SurfaceInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)SurfaceInfo.Length;
            for (int j = 0; j < SurfaceInfo.Length; j++) { SurfaceInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ObjectData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ObjectData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int SurfaceInfoStart = 0;
            do
            {
                int variableLength = 0;
                int SurfaceInfoCount = 0;

                i = SurfaceInfoStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < SurfaceInfo.Length) {
                    int blockLength = SurfaceInfo[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++SurfaceInfoCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)SurfaceInfoCount;
                for (i = SurfaceInfoStart; i < SurfaceInfoStart + SurfaceInfoCount; i++) { SurfaceInfo[i].ToBytes(packet, ref length); }
                SurfaceInfoStart += SurfaceInfoCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                SurfaceInfoStart < SurfaceInfo.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectGrabUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;
            public Vector3 GrabOffsetInitial;
            public Vector3 GrabPosition;
            public uint TimeSinceLast;

            public override int Length
            {
                get
                {
                    return 44;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    GrabOffsetInitial.FromBytes(bytes, i); i += 12;
                    GrabPosition.FromBytes(bytes, i); i += 12;
                    TimeSinceLast = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                GrabOffsetInitial.ToBytes(bytes, i); i += 12;
                GrabPosition.ToBytes(bytes, i); i += 12;
                Utils.UIntToBytes(TimeSinceLast, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class SurfaceInfoBlock : PacketBlock
        {
            public Vector3 UVCoord;
            public Vector3 STCoord;
            public int FaceIndex;
            public Vector3 Position;
            public Vector3 Normal;
            public Vector3 Binormal;

            public override int Length
            {
                get
                {
                    return 64;
                }
            }

            public SurfaceInfoBlock() { }
            public SurfaceInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    UVCoord.FromBytes(bytes, i); i += 12;
                    STCoord.FromBytes(bytes, i); i += 12;
                    FaceIndex = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Position.FromBytes(bytes, i); i += 12;
                    Normal.FromBytes(bytes, i); i += 12;
                    Binormal.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                UVCoord.ToBytes(bytes, i); i += 12;
                STCoord.ToBytes(bytes, i); i += 12;
                Utils.IntToBytes(FaceIndex, bytes, i); i += 4;
                Position.ToBytes(bytes, i); i += 12;
                Normal.ToBytes(bytes, i); i += 12;
                Binormal.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += ObjectData.Length;
                for (int j = 0; j < SurfaceInfo.Length; j++)
                    length += SurfaceInfo[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;
        public SurfaceInfoBlock[] SurfaceInfo;

        public ObjectGrabUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectGrabUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 118;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
            SurfaceInfo = null;
        }

        public ObjectGrabUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SurfaceInfo == null || SurfaceInfo.Length != -1) {
                SurfaceInfo = new SurfaceInfoBlock[count];
                for(int j = 0; j < count; j++)
                { SurfaceInfo[j] = new SurfaceInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SurfaceInfo[j].FromBytes(bytes, ref i); }
        }

        public ObjectGrabUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SurfaceInfo == null || SurfaceInfo.Length != count) {
                SurfaceInfo = new SurfaceInfoBlock[count];
                for(int j = 0; j < count; j++)
                { SurfaceInfo[j] = new SurfaceInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SurfaceInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < SurfaceInfo.Length; j++) { length += SurfaceInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)SurfaceInfo.Length;
            for (int j = 0; j < SurfaceInfo.Length; j++) { SurfaceInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ObjectData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ObjectData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int SurfaceInfoStart = 0;
            do
            {
                int variableLength = 0;
                int SurfaceInfoCount = 0;

                i = SurfaceInfoStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < SurfaceInfo.Length) {
                    int blockLength = SurfaceInfo[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++SurfaceInfoCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)SurfaceInfoCount;
                for (i = SurfaceInfoStart; i < SurfaceInfoStart + SurfaceInfoCount; i++) { SurfaceInfo[i].ToBytes(packet, ref length); }
                SurfaceInfoStart += SurfaceInfoCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                SurfaceInfoStart < SurfaceInfo.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectDeGrabPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class SurfaceInfoBlock : PacketBlock
        {
            public Vector3 UVCoord;
            public Vector3 STCoord;
            public int FaceIndex;
            public Vector3 Position;
            public Vector3 Normal;
            public Vector3 Binormal;

            public override int Length
            {
                get
                {
                    return 64;
                }
            }

            public SurfaceInfoBlock() { }
            public SurfaceInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    UVCoord.FromBytes(bytes, i); i += 12;
                    STCoord.FromBytes(bytes, i); i += 12;
                    FaceIndex = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Position.FromBytes(bytes, i); i += 12;
                    Normal.FromBytes(bytes, i); i += 12;
                    Binormal.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                UVCoord.ToBytes(bytes, i); i += 12;
                STCoord.ToBytes(bytes, i); i += 12;
                Utils.IntToBytes(FaceIndex, bytes, i); i += 4;
                Position.ToBytes(bytes, i); i += 12;
                Normal.ToBytes(bytes, i); i += 12;
                Binormal.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += ObjectData.Length;
                for (int j = 0; j < SurfaceInfo.Length; j++)
                    length += SurfaceInfo[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;
        public SurfaceInfoBlock[] SurfaceInfo;

        public ObjectDeGrabPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectDeGrab;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 119;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
            SurfaceInfo = null;
        }

        public ObjectDeGrabPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SurfaceInfo == null || SurfaceInfo.Length != -1) {
                SurfaceInfo = new SurfaceInfoBlock[count];
                for(int j = 0; j < count; j++)
                { SurfaceInfo[j] = new SurfaceInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SurfaceInfo[j].FromBytes(bytes, ref i); }
        }

        public ObjectDeGrabPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SurfaceInfo == null || SurfaceInfo.Length != count) {
                SurfaceInfo = new SurfaceInfoBlock[count];
                for(int j = 0; j < count; j++)
                { SurfaceInfo[j] = new SurfaceInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SurfaceInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < SurfaceInfo.Length; j++) { length += SurfaceInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)SurfaceInfo.Length;
            for (int j = 0; j < SurfaceInfo.Length; j++) { SurfaceInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ObjectData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ObjectData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int SurfaceInfoStart = 0;
            do
            {
                int variableLength = 0;
                int SurfaceInfoCount = 0;

                i = SurfaceInfoStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < SurfaceInfo.Length) {
                    int blockLength = SurfaceInfo[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++SurfaceInfoCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)SurfaceInfoCount;
                for (i = SurfaceInfoStart; i < SurfaceInfoStart + SurfaceInfoCount; i++) { SurfaceInfo[i].ToBytes(packet, ref length); }
                SurfaceInfoStart += SurfaceInfoCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                SurfaceInfoStart < SurfaceInfo.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectSpinStartPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ObjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;

        public ObjectSpinStartPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ObjectSpinStart;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 120;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
        }

        public ObjectSpinStartPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public ObjectSpinStartPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectSpinUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;
            public Quaternion Rotation;

            public override int Length
            {
                get
                {
                    return 28;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    Rotation.FromBytes(bytes, i, true); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                Rotation.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ObjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;

        public ObjectSpinUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ObjectSpinUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 121;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
        }

        public ObjectSpinUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public ObjectSpinUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectSpinStopPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ObjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;

        public ObjectSpinStopPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ObjectSpinStop;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 122;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
        }

        public ObjectSpinStopPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public ObjectSpinStopPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectExportSelectedPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID RequestID;
            public short VolumeDetail;

            public override int Length
            {
                get
                {
                    return 34;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                    VolumeDetail = (short)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(VolumeDetail % 256);
                bytes[i++] = (byte)((VolumeDetail >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectExportSelectedPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectExportSelected;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 123;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectExportSelectedPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectExportSelectedPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ModifyLandPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ModifyBlockBlock : PacketBlock
        {
            public byte Action;
            public byte BrushSize;
            public float Seconds;
            public float Height;

            public override int Length
            {
                get
                {
                    return 10;
                }
            }

            public ModifyBlockBlock() { }
            public ModifyBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Action = (byte)bytes[i++];
                    BrushSize = (byte)bytes[i++];
                    Seconds = Utils.BytesToFloat(bytes, i); i += 4;
                    Height = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = Action;
                bytes[i++] = BrushSize;
                Utils.FloatToBytes(Seconds, bytes, i); i += 4;
                Utils.FloatToBytes(Height, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public float West;
            public float South;
            public float East;
            public float North;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    West = Utils.BytesToFloat(bytes, i); i += 4;
                    South = Utils.BytesToFloat(bytes, i); i += 4;
                    East = Utils.BytesToFloat(bytes, i); i += 4;
                    North = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                Utils.FloatToBytes(West, bytes, i); i += 4;
                Utils.FloatToBytes(South, bytes, i); i += 4;
                Utils.FloatToBytes(East, bytes, i); i += 4;
                Utils.FloatToBytes(North, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ModifyBlockExtendedBlock : PacketBlock
        {
            public float BrushSize;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ModifyBlockExtendedBlock() { }
            public ModifyBlockExtendedBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    BrushSize = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.FloatToBytes(BrushSize, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                length += ModifyBlock.Length;
                for (int j = 0; j < ParcelData.Length; j++)
                    length += ParcelData[j].Length;
                for (int j = 0; j < ModifyBlockExtended.Length; j++)
                    length += ModifyBlockExtended[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ModifyBlockBlock ModifyBlock;
        public ParcelDataBlock[] ParcelData;
        public ModifyBlockExtendedBlock[] ModifyBlockExtended;

        public ModifyLandPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ModifyLand;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 124;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ModifyBlock = new ModifyBlockBlock();
            ParcelData = null;
            ModifyBlockExtended = null;
        }

        public ModifyLandPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ModifyBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParcelData == null || ParcelData.Length != -1) {
                ParcelData = new ParcelDataBlock[count];
                for(int j = 0; j < count; j++)
                { ParcelData[j] = new ParcelDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParcelData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ModifyBlockExtended == null || ModifyBlockExtended.Length != -1) {
                ModifyBlockExtended = new ModifyBlockExtendedBlock[count];
                for(int j = 0; j < count; j++)
                { ModifyBlockExtended[j] = new ModifyBlockExtendedBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ModifyBlockExtended[j].FromBytes(bytes, ref i); }
        }

        public ModifyLandPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ModifyBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParcelData == null || ParcelData.Length != count) {
                ParcelData = new ParcelDataBlock[count];
                for(int j = 0; j < count; j++)
                { ParcelData[j] = new ParcelDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParcelData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ModifyBlockExtended == null || ModifyBlockExtended.Length != count) {
                ModifyBlockExtended = new ModifyBlockExtendedBlock[count];
                for(int j = 0; j < count; j++)
                { ModifyBlockExtended[j] = new ModifyBlockExtendedBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ModifyBlockExtended[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ModifyBlock.Length;
            length++;
            for (int j = 0; j < ParcelData.Length; j++) { length += ParcelData[j].Length; }
            length++;
            for (int j = 0; j < ModifyBlockExtended.Length; j++) { length += ModifyBlockExtended[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ModifyBlock.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ParcelData.Length;
            for (int j = 0; j < ParcelData.Length; j++) { ParcelData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)ModifyBlockExtended.Length;
            for (int j = 0; j < ModifyBlockExtended.Length; j++) { ModifyBlockExtended[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ModifyBlock.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ModifyBlock.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int ParcelDataStart = 0;
            int ModifyBlockExtendedStart = 0;
            do
            {
                int variableLength = 0;
                int ParcelDataCount = 0;
                int ModifyBlockExtendedCount = 0;

                i = ParcelDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ParcelData.Length) {
                    int blockLength = ParcelData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ParcelDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = ModifyBlockExtendedStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ModifyBlockExtended.Length) {
                    int blockLength = ModifyBlockExtended[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ModifyBlockExtendedCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ParcelDataCount;
                for (i = ParcelDataStart; i < ParcelDataStart + ParcelDataCount; i++) { ParcelData[i].ToBytes(packet, ref length); }
                ParcelDataStart += ParcelDataCount;

                packet[length++] = (byte)ModifyBlockExtendedCount;
                for (i = ModifyBlockExtendedStart; i < ModifyBlockExtendedStart + ModifyBlockExtendedCount; i++) { ModifyBlockExtended[i].ToBytes(packet, ref length); }
                ModifyBlockExtendedStart += ModifyBlockExtendedCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ParcelDataStart < ParcelData.Length ||
                ModifyBlockExtendedStart < ModifyBlockExtended.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class VelocityInterpolateOnPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public VelocityInterpolateOnPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.VelocityInterpolateOn;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 125;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public VelocityInterpolateOnPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public VelocityInterpolateOnPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class VelocityInterpolateOffPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public VelocityInterpolateOffPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.VelocityInterpolateOff;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 126;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public VelocityInterpolateOffPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public VelocityInterpolateOffPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class StateSavePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlockBlock : PacketBlock
        {
            public byte[] Filename;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Filename != null) { length += Filename.Length; }
                    return length;
                }
            }

            public DataBlockBlock() { }
            public DataBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Filename = new byte[length];
                    Buffer.BlockCopy(bytes, i, Filename, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Filename.Length;
                Buffer.BlockCopy(Filename, 0, bytes, i, Filename.Length); i += Filename.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += DataBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlockBlock DataBlock;

        public StateSavePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.StateSave;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 127;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            DataBlock = new DataBlockBlock();
        }

        public StateSavePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            DataBlock.FromBytes(bytes, ref i);
        }

        public StateSavePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            DataBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += DataBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            DataBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ReportAutosaveCrashPacket : Packet
    {
        /// <exclude/>
        public sealed class AutosaveDataBlock : PacketBlock
        {
            public int PID;
            public int Status;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public AutosaveDataBlock() { }
            public AutosaveDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Status = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(PID, bytes, i); i += 4;
                Utils.IntToBytes(Status, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AutosaveData.Length;
                return length;
            }
        }
        public AutosaveDataBlock AutosaveData;

        public ReportAutosaveCrashPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ReportAutosaveCrash;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 128;
            Header.Reliable = true;
            AutosaveData = new AutosaveDataBlock();
        }

        public ReportAutosaveCrashPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AutosaveData.FromBytes(bytes, ref i);
        }

        public ReportAutosaveCrashPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AutosaveData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AutosaveData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AutosaveData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SimWideDeletesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlockBlock : PacketBlock
        {
            public UUID TargetID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlockBlock() { }
            public DataBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += DataBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlockBlock DataBlock;

        public SimWideDeletesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SimWideDeletes;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 129;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            DataBlock = new DataBlockBlock();
        }

        public SimWideDeletesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            DataBlock.FromBytes(bytes, ref i);
        }

        public SimWideDeletesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            DataBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += DataBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            DataBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TrackAgentPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TargetDataBlock : PacketBlock
        {
            public UUID PreyID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TargetDataBlock() { }
            public TargetDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PreyID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                PreyID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += TargetData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TargetDataBlock TargetData;

        public TrackAgentPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TrackAgent;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 130;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            TargetData = new TargetDataBlock();
        }

        public TrackAgentPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TargetData.FromBytes(bytes, ref i);
        }

        public TrackAgentPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TargetData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TargetData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TargetData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ViewerStatsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint IP;
            public uint StartTime;
            public float RunTime;
            public float SimFPS;
            public float FPS;
            public byte AgentsInView;
            public float Ping;
            public double MetersTraveled;
            public int RegionsVisited;
            public uint SysRAM;
            public byte[] SysOS;
            public byte[] SysCPU;
            public byte[] SysGPU;

            public override int Length
            {
                get
                {
                    int length = 76;
                    if (SysOS != null) { length += SysOS.Length; }
                    if (SysCPU != null) { length += SysCPU.Length; }
                    if (SysGPU != null) { length += SysGPU.Length; }
                    return length;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    IP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    StartTime = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RunTime = Utils.BytesToFloat(bytes, i); i += 4;
                    SimFPS = Utils.BytesToFloat(bytes, i); i += 4;
                    FPS = Utils.BytesToFloat(bytes, i); i += 4;
                    AgentsInView = (byte)bytes[i++];
                    Ping = Utils.BytesToFloat(bytes, i); i += 4;
                    MetersTraveled = Utils.BytesToDouble(bytes, i); i += 8;
                    RegionsVisited = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SysRAM = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    SysOS = new byte[length];
                    Buffer.BlockCopy(bytes, i, SysOS, 0, length); i += length;
                    length = bytes[i++];
                    SysCPU = new byte[length];
                    Buffer.BlockCopy(bytes, i, SysCPU, 0, length); i += length;
                    length = bytes[i++];
                    SysGPU = new byte[length];
                    Buffer.BlockCopy(bytes, i, SysGPU, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(IP, bytes, i); i += 4;
                Utils.UIntToBytes(StartTime, bytes, i); i += 4;
                Utils.FloatToBytes(RunTime, bytes, i); i += 4;
                Utils.FloatToBytes(SimFPS, bytes, i); i += 4;
                Utils.FloatToBytes(FPS, bytes, i); i += 4;
                bytes[i++] = AgentsInView;
                Utils.FloatToBytes(Ping, bytes, i); i += 4;
                Utils.DoubleToBytes(MetersTraveled, bytes, i); i += 8;
                Utils.IntToBytes(RegionsVisited, bytes, i); i += 4;
                Utils.UIntToBytes(SysRAM, bytes, i); i += 4;
                bytes[i++] = (byte)SysOS.Length;
                Buffer.BlockCopy(SysOS, 0, bytes, i, SysOS.Length); i += SysOS.Length;
                bytes[i++] = (byte)SysCPU.Length;
                Buffer.BlockCopy(SysCPU, 0, bytes, i, SysCPU.Length); i += SysCPU.Length;
                bytes[i++] = (byte)SysGPU.Length;
                Buffer.BlockCopy(SysGPU, 0, bytes, i, SysGPU.Length); i += SysGPU.Length;
            }

        }

        /// <exclude/>
        public sealed class DownloadTotalsBlock : PacketBlock
        {
            public uint World;
            public uint Objects;
            public uint Textures;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public DownloadTotalsBlock() { }
            public DownloadTotalsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    World = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Objects = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Textures = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(World, bytes, i); i += 4;
                Utils.UIntToBytes(Objects, bytes, i); i += 4;
                Utils.UIntToBytes(Textures, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class NetStatsBlock : PacketBlock
        {
            public uint Bytes;
            public uint Packets;
            public uint Compressed;
            public uint Savings;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public NetStatsBlock() { }
            public NetStatsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Bytes = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Packets = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Compressed = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Savings = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Bytes, bytes, i); i += 4;
                Utils.UIntToBytes(Packets, bytes, i); i += 4;
                Utils.UIntToBytes(Compressed, bytes, i); i += 4;
                Utils.UIntToBytes(Savings, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class FailStatsBlock : PacketBlock
        {
            public uint SendPacket;
            public uint Dropped;
            public uint Resent;
            public uint FailedResends;
            public uint OffCircuit;
            public uint Invalid;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public FailStatsBlock() { }
            public FailStatsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SendPacket = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Dropped = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Resent = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    FailedResends = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OffCircuit = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Invalid = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(SendPacket, bytes, i); i += 4;
                Utils.UIntToBytes(Dropped, bytes, i); i += 4;
                Utils.UIntToBytes(Resent, bytes, i); i += 4;
                Utils.UIntToBytes(FailedResends, bytes, i); i += 4;
                Utils.UIntToBytes(OffCircuit, bytes, i); i += 4;
                Utils.UIntToBytes(Invalid, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class MiscStatsBlock : PacketBlock
        {
            public uint Type;
            public double Value;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public MiscStatsBlock() { }
            public MiscStatsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Type = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Value = Utils.BytesToDouble(bytes, i); i += 8;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Type, bytes, i); i += 4;
                Utils.DoubleToBytes(Value, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += DownloadTotals.Length;
                for (int j = 0; j < 2; j++)
                    length += NetStats[j].Length;
                length += FailStats.Length;
                for (int j = 0; j < MiscStats.Length; j++)
                    length += MiscStats[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DownloadTotalsBlock DownloadTotals;
        public NetStatsBlock[] NetStats;
        public FailStatsBlock FailStats;
        public MiscStatsBlock[] MiscStats;

        public ViewerStatsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ViewerStats;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 131;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            DownloadTotals = new DownloadTotalsBlock();
            NetStats = new NetStatsBlock[2];
            FailStats = new FailStatsBlock();
            MiscStats = null;
        }

        public ViewerStatsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            DownloadTotals.FromBytes(bytes, ref i);
            if(NetStats == null || NetStats.Length != 2) {
                NetStats = new NetStatsBlock[2];
                for(int j = 0; j < 2; j++)
                { NetStats[j] = new NetStatsBlock(); }
            }
            for (int j = 0; j < 2; j++)
            { NetStats[j].FromBytes(bytes, ref i); }
            FailStats.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(MiscStats == null || MiscStats.Length != -1) {
                MiscStats = new MiscStatsBlock[count];
                for(int j = 0; j < count; j++)
                { MiscStats[j] = new MiscStatsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MiscStats[j].FromBytes(bytes, ref i); }
        }

        public ViewerStatsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            DownloadTotals.FromBytes(bytes, ref i);
            if(NetStats == null || NetStats.Length != 2) {
                NetStats = new NetStatsBlock[2];
                for(int j = 0; j < 2; j++)
                { NetStats[j] = new NetStatsBlock(); }
            }
            for (int j = 0; j < 2; j++)
            { NetStats[j].FromBytes(bytes, ref i); }
            FailStats.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(MiscStats == null || MiscStats.Length != count) {
                MiscStats = new MiscStatsBlock[count];
                for(int j = 0; j < count; j++)
                { MiscStats[j] = new MiscStatsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MiscStats[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += DownloadTotals.Length;
            length += FailStats.Length;
            for (int j = 0; j < 2; j++) { length += NetStats[j].Length; }
            length++;
            for (int j = 0; j < MiscStats.Length; j++) { length += MiscStats[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            DownloadTotals.ToBytes(bytes, ref i);
            for (int j = 0; j < 2; j++) { NetStats[j].ToBytes(bytes, ref i); }
            FailStats.ToBytes(bytes, ref i);
            bytes[i++] = (byte)MiscStats.Length;
            for (int j = 0; j < MiscStats.Length; j++) { MiscStats[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += DownloadTotals.Length;
            for (int j = 0; j < 2; j++) { fixedLength += NetStats[j].Length; }
            fixedLength += FailStats.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            DownloadTotals.ToBytes(fixedBytes, ref i);
            for (int j = 0; j < 2; j++) { NetStats[j].ToBytes(fixedBytes, ref i); }
            FailStats.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int MiscStatsStart = 0;
            do
            {
                int variableLength = 0;
                int MiscStatsCount = 0;

                i = MiscStatsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < MiscStats.Length) {
                    int blockLength = MiscStats[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++MiscStatsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)MiscStatsCount;
                for (i = MiscStatsStart; i < MiscStatsStart + MiscStatsCount; i++) { MiscStats[i].ToBytes(packet, ref length); }
                MiscStatsStart += MiscStatsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                MiscStatsStart < MiscStats.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ScriptAnswerYesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID TaskID;
            public UUID ItemID;
            public int Questions;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TaskID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                    Questions = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TaskID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Questions, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ScriptAnswerYesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptAnswerYes;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 132;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ScriptAnswerYesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ScriptAnswerYesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UserReportPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ReportDataBlock : PacketBlock
        {
            public byte ReportType;
            public byte Category;
            public Vector3 Position;
            public byte CheckFlags;
            public UUID ScreenshotID;
            public UUID ObjectID;
            public UUID AbuserID;
            public byte[] AbuseRegionName;
            public UUID AbuseRegionID;
            public byte[] Summary;
            public byte[] Details;
            public byte[] VersionString;

            public override int Length
            {
                get
                {
                    int length = 84;
                    if (AbuseRegionName != null) { length += AbuseRegionName.Length; }
                    if (Summary != null) { length += Summary.Length; }
                    if (Details != null) { length += Details.Length; }
                    if (VersionString != null) { length += VersionString.Length; }
                    return length;
                }
            }

            public ReportDataBlock() { }
            public ReportDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ReportType = (byte)bytes[i++];
                    Category = (byte)bytes[i++];
                    Position.FromBytes(bytes, i); i += 12;
                    CheckFlags = (byte)bytes[i++];
                    ScreenshotID.FromBytes(bytes, i); i += 16;
                    ObjectID.FromBytes(bytes, i); i += 16;
                    AbuserID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    AbuseRegionName = new byte[length];
                    Buffer.BlockCopy(bytes, i, AbuseRegionName, 0, length); i += length;
                    AbuseRegionID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Summary = new byte[length];
                    Buffer.BlockCopy(bytes, i, Summary, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Details = new byte[length];
                    Buffer.BlockCopy(bytes, i, Details, 0, length); i += length;
                    length = bytes[i++];
                    VersionString = new byte[length];
                    Buffer.BlockCopy(bytes, i, VersionString, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = ReportType;
                bytes[i++] = Category;
                Position.ToBytes(bytes, i); i += 12;
                bytes[i++] = CheckFlags;
                ScreenshotID.ToBytes(bytes, i); i += 16;
                ObjectID.ToBytes(bytes, i); i += 16;
                AbuserID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)AbuseRegionName.Length;
                Buffer.BlockCopy(AbuseRegionName, 0, bytes, i, AbuseRegionName.Length); i += AbuseRegionName.Length;
                AbuseRegionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Summary.Length;
                Buffer.BlockCopy(Summary, 0, bytes, i, Summary.Length); i += Summary.Length;
                bytes[i++] = (byte)(Details.Length % 256);
                bytes[i++] = (byte)((Details.Length >> 8) % 256);
                Buffer.BlockCopy(Details, 0, bytes, i, Details.Length); i += Details.Length;
                bytes[i++] = (byte)VersionString.Length;
                Buffer.BlockCopy(VersionString, 0, bytes, i, VersionString.Length); i += VersionString.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ReportData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ReportDataBlock ReportData;

        public UserReportPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UserReport;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 133;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ReportData = new ReportDataBlock();
        }

        public UserReportPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ReportData.FromBytes(bytes, ref i);
        }

        public UserReportPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ReportData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ReportData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ReportData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AlertMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class AlertDataBlock : PacketBlock
        {
            public byte[] Message;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public AlertDataBlock() { }
            public AlertDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
            }

        }

        /// <exclude/>
        public sealed class AlertInfoBlock : PacketBlock
        {
            public byte[] Message;
            public byte[] ExtraParams;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Message != null) { length += Message.Length; }
                    if (ExtraParams != null) { length += ExtraParams.Length; }
                    return length;
                }
            }

            public AlertInfoBlock() { }
            public AlertInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    length = bytes[i++];
                    ExtraParams = new byte[length];
                    Buffer.BlockCopy(bytes, i, ExtraParams, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                bytes[i++] = (byte)ExtraParams.Length;
                Buffer.BlockCopy(ExtraParams, 0, bytes, i, ExtraParams.Length); i += ExtraParams.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AlertData.Length;
                for (int j = 0; j < AlertInfo.Length; j++)
                    length += AlertInfo[j].Length;
                return length;
            }
        }
        public AlertDataBlock AlertData;
        public AlertInfoBlock[] AlertInfo;

        public AlertMessagePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AlertMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 134;
            Header.Reliable = true;
            AlertData = new AlertDataBlock();
            AlertInfo = null;
        }

        public AlertMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AlertData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AlertInfo == null || AlertInfo.Length != -1) {
                AlertInfo = new AlertInfoBlock[count];
                for(int j = 0; j < count; j++)
                { AlertInfo[j] = new AlertInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AlertInfo[j].FromBytes(bytes, ref i); }
        }

        public AlertMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AlertData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AlertInfo == null || AlertInfo.Length != count) {
                AlertInfo = new AlertInfoBlock[count];
                for(int j = 0; j < count; j++)
                { AlertInfo[j] = new AlertInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AlertInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AlertData.Length;
            length++;
            for (int j = 0; j < AlertInfo.Length; j++) { length += AlertInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AlertData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AlertInfo.Length;
            for (int j = 0; j < AlertInfo.Length; j++) { AlertInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AlertData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AlertData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int AlertInfoStart = 0;
            do
            {
                int variableLength = 0;
                int AlertInfoCount = 0;

                i = AlertInfoStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AlertInfo.Length) {
                    int blockLength = AlertInfo[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AlertInfoCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AlertInfoCount;
                for (i = AlertInfoStart; i < AlertInfoStart + AlertInfoCount; i++) { AlertInfo[i].ToBytes(packet, ref length); }
                AlertInfoStart += AlertInfoCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AlertInfoStart < AlertInfo.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentAlertMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class AlertDataBlock : PacketBlock
        {
            public bool Modal;
            public byte[] Message;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public AlertDataBlock() { }
            public AlertDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    Modal = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((Modal) ? 1 : 0);
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += AlertData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public AlertDataBlock AlertData;

        public AgentAlertMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentAlertMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 135;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            AlertData = new AlertDataBlock();
        }

        public AgentAlertMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            AlertData.FromBytes(bytes, ref i);
        }

        public AgentAlertMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            AlertData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += AlertData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            AlertData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MeanCollisionAlertPacket : Packet
    {
        /// <exclude/>
        public sealed class MeanCollisionBlock : PacketBlock
        {
            public UUID Victim;
            public UUID Perp;
            public uint Time;
            public float Mag;
            public byte Type;

            public override int Length
            {
                get
                {
                    return 41;
                }
            }

            public MeanCollisionBlock() { }
            public MeanCollisionBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Victim.FromBytes(bytes, i); i += 16;
                    Perp.FromBytes(bytes, i); i += 16;
                    Time = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Mag = Utils.BytesToFloat(bytes, i); i += 4;
                    Type = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Victim.ToBytes(bytes, i); i += 16;
                Perp.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Time, bytes, i); i += 4;
                Utils.FloatToBytes(Mag, bytes, i); i += 4;
                bytes[i++] = Type;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < MeanCollision.Length; j++)
                    length += MeanCollision[j].Length;
                return length;
            }
        }
        public MeanCollisionBlock[] MeanCollision;

        public MeanCollisionAlertPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MeanCollisionAlert;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 136;
            Header.Reliable = true;
            Header.Zerocoded = true;
            MeanCollision = null;
        }

        public MeanCollisionAlertPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(MeanCollision == null || MeanCollision.Length != -1) {
                MeanCollision = new MeanCollisionBlock[count];
                for(int j = 0; j < count; j++)
                { MeanCollision[j] = new MeanCollisionBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MeanCollision[j].FromBytes(bytes, ref i); }
        }

        public MeanCollisionAlertPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(MeanCollision == null || MeanCollision.Length != count) {
                MeanCollision = new MeanCollisionBlock[count];
                for(int j = 0; j < count; j++)
                { MeanCollision[j] = new MeanCollisionBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MeanCollision[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < MeanCollision.Length; j++) { length += MeanCollision[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)MeanCollision.Length;
            for (int j = 0; j < MeanCollision.Length; j++) { MeanCollision[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int MeanCollisionStart = 0;
            do
            {
                int variableLength = 0;
                int MeanCollisionCount = 0;

                i = MeanCollisionStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < MeanCollision.Length) {
                    int blockLength = MeanCollision[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++MeanCollisionCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)MeanCollisionCount;
                for (i = MeanCollisionStart; i < MeanCollisionStart + MeanCollisionCount; i++) { MeanCollision[i].ToBytes(packet, ref length); }
                MeanCollisionStart += MeanCollisionCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                MeanCollisionStart < MeanCollision.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ViewerFrozenMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class FrozenDataBlock : PacketBlock
        {
            public bool Data;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public FrozenDataBlock() { }
            public FrozenDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Data = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((Data) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += FrozenData.Length;
                return length;
            }
        }
        public FrozenDataBlock FrozenData;

        public ViewerFrozenMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ViewerFrozenMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 137;
            Header.Reliable = true;
            FrozenData = new FrozenDataBlock();
        }

        public ViewerFrozenMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            FrozenData.FromBytes(bytes, ref i);
        }

        public ViewerFrozenMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            FrozenData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += FrozenData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            FrozenData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class HealthMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class HealthDataBlock : PacketBlock
        {
            public float Health;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public HealthDataBlock() { }
            public HealthDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Health = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.FloatToBytes(Health, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += HealthData.Length;
                return length;
            }
        }
        public HealthDataBlock HealthData;

        public HealthMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.HealthMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 138;
            Header.Reliable = true;
            Header.Zerocoded = true;
            HealthData = new HealthDataBlock();
        }

        public HealthMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            HealthData.FromBytes(bytes, ref i);
        }

        public HealthMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            HealthData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += HealthData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            HealthData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ChatFromSimulatorPacket : Packet
    {
        /// <exclude/>
        public sealed class ChatDataBlock : PacketBlock
        {
            public byte[] FromName;
            public UUID SourceID;
            public UUID OwnerID;
            public byte SourceType;
            public byte ChatType;
            public byte Audible;
            public Vector3 Position;
            public byte[] Message;

            public override int Length
            {
                get
                {
                    int length = 50;
                    if (FromName != null) { length += FromName.Length; }
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public ChatDataBlock() { }
            public ChatDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    FromName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FromName, 0, length); i += length;
                    SourceID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    SourceType = (byte)bytes[i++];
                    ChatType = (byte)bytes[i++];
                    Audible = (byte)bytes[i++];
                    Position.FromBytes(bytes, i); i += 12;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)FromName.Length;
                Buffer.BlockCopy(FromName, 0, bytes, i, FromName.Length); i += FromName.Length;
                SourceID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = SourceType;
                bytes[i++] = ChatType;
                bytes[i++] = Audible;
                Position.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)(Message.Length % 256);
                bytes[i++] = (byte)((Message.Length >> 8) % 256);
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ChatData.Length;
                return length;
            }
        }
        public ChatDataBlock ChatData;

        public ChatFromSimulatorPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ChatFromSimulator;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 139;
            Header.Reliable = true;
            ChatData = new ChatDataBlock();
        }

        public ChatFromSimulatorPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ChatData.FromBytes(bytes, ref i);
        }

        public ChatFromSimulatorPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ChatData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ChatData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ChatData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SimStatsPacket : Packet
    {
        /// <exclude/>
        public sealed class RegionBlock : PacketBlock
        {
            public uint RegionX;
            public uint RegionY;
            public uint RegionFlags;
            public uint ObjectCapacity;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public RegionBlock() { }
            public RegionBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionX = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RegionY = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RegionFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ObjectCapacity = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(RegionX, bytes, i); i += 4;
                Utils.UIntToBytes(RegionY, bytes, i); i += 4;
                Utils.UIntToBytes(RegionFlags, bytes, i); i += 4;
                Utils.UIntToBytes(ObjectCapacity, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class StatBlock : PacketBlock
        {
            public uint StatID;
            public float StatValue;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public StatBlock() { }
            public StatBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    StatID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    StatValue = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(StatID, bytes, i); i += 4;
                Utils.FloatToBytes(StatValue, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class PidStatBlock : PacketBlock
        {
            public int PID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public PidStatBlock() { }
            public PidStatBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(PID, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RegionInfoBlock : PacketBlock
        {
            public ulong RegionFlagsExtended;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public RegionInfoBlock() { }
            public RegionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionFlagsExtended = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionFlagsExtended, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += Region.Length;
                for (int j = 0; j < Stat.Length; j++)
                    length += Stat[j].Length;
                length += PidStat.Length;
                for (int j = 0; j < RegionInfo.Length; j++)
                    length += RegionInfo[j].Length;
                return length;
            }
        }
        public RegionBlock Region;
        public StatBlock[] Stat;
        public PidStatBlock PidStat;
        public RegionInfoBlock[] RegionInfo;

        public SimStatsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.SimStats;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 140;
            Header.Reliable = true;
            Region = new RegionBlock();
            Stat = null;
            PidStat = new PidStatBlock();
            RegionInfo = null;
        }

        public SimStatsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Region.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Stat == null || Stat.Length != -1) {
                Stat = new StatBlock[count];
                for(int j = 0; j < count; j++)
                { Stat[j] = new StatBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Stat[j].FromBytes(bytes, ref i); }
            PidStat.FromBytes(bytes, ref i);
            count = (int)bytes[i++];
            if(RegionInfo == null || RegionInfo.Length != -1) {
                RegionInfo = new RegionInfoBlock[count];
                for(int j = 0; j < count; j++)
                { RegionInfo[j] = new RegionInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo[j].FromBytes(bytes, ref i); }
        }

        public SimStatsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Region.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Stat == null || Stat.Length != count) {
                Stat = new StatBlock[count];
                for(int j = 0; j < count; j++)
                { Stat[j] = new StatBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Stat[j].FromBytes(bytes, ref i); }
            PidStat.FromBytes(bytes, ref i);
            count = (int)bytes[i++];
            if(RegionInfo == null || RegionInfo.Length != count) {
                RegionInfo = new RegionInfoBlock[count];
                for(int j = 0; j < count; j++)
                { RegionInfo[j] = new RegionInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Region.Length;
            length += PidStat.Length;
            length++;
            for (int j = 0; j < Stat.Length; j++) { length += Stat[j].Length; }
            length++;
            for (int j = 0; j < RegionInfo.Length; j++) { length += RegionInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Region.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Stat.Length;
            for (int j = 0; j < Stat.Length; j++) { Stat[j].ToBytes(bytes, ref i); }
            PidStat.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RegionInfo.Length;
            for (int j = 0; j < RegionInfo.Length; j++) { RegionInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RequestRegionInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public RequestRegionInfoPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RequestRegionInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 141;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public RequestRegionInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public RequestRegionInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RegionInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RegionInfoBlock : PacketBlock
        {
            public byte[] SimName;
            public uint EstateID;
            public uint ParentEstateID;
            public uint RegionFlags;
            public byte SimAccess;
            public byte MaxAgents;
            public float BillableFactor;
            public float ObjectBonusFactor;
            public float WaterHeight;
            public float TerrainRaiseLimit;
            public float TerrainLowerLimit;
            public int PricePerMeter;
            public int RedirectGridX;
            public int RedirectGridY;
            public bool UseEstateSun;
            public float SunHour;

            public override int Length
            {
                get
                {
                    int length = 52;
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public RegionInfoBlock() { }
            public RegionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    EstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParentEstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RegionFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SimAccess = (byte)bytes[i++];
                    MaxAgents = (byte)bytes[i++];
                    BillableFactor = Utils.BytesToFloat(bytes, i); i += 4;
                    ObjectBonusFactor = Utils.BytesToFloat(bytes, i); i += 4;
                    WaterHeight = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainRaiseLimit = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainLowerLimit = Utils.BytesToFloat(bytes, i); i += 4;
                    PricePerMeter = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RedirectGridX = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RedirectGridY = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    UseEstateSun = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    SunHour = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                Utils.UIntToBytes(EstateID, bytes, i); i += 4;
                Utils.UIntToBytes(ParentEstateID, bytes, i); i += 4;
                Utils.UIntToBytes(RegionFlags, bytes, i); i += 4;
                bytes[i++] = SimAccess;
                bytes[i++] = MaxAgents;
                Utils.FloatToBytes(BillableFactor, bytes, i); i += 4;
                Utils.FloatToBytes(ObjectBonusFactor, bytes, i); i += 4;
                Utils.FloatToBytes(WaterHeight, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainRaiseLimit, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainLowerLimit, bytes, i); i += 4;
                Utils.IntToBytes(PricePerMeter, bytes, i); i += 4;
                Utils.IntToBytes(RedirectGridX, bytes, i); i += 4;
                Utils.IntToBytes(RedirectGridY, bytes, i); i += 4;
                bytes[i++] = (byte)((UseEstateSun) ? 1 : 0);
                Utils.FloatToBytes(SunHour, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RegionInfo2Block : PacketBlock
        {
            public byte[] ProductSKU;
            public byte[] ProductName;
            public uint MaxAgents32;
            public uint HardMaxAgents;
            public uint HardMaxObjects;

            public override int Length
            {
                get
                {
                    int length = 14;
                    if (ProductSKU != null) { length += ProductSKU.Length; }
                    if (ProductName != null) { length += ProductName.Length; }
                    return length;
                }
            }

            public RegionInfo2Block() { }
            public RegionInfo2Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    ProductSKU = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProductSKU, 0, length); i += length;
                    length = bytes[i++];
                    ProductName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProductName, 0, length); i += length;
                    MaxAgents32 = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    HardMaxAgents = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    HardMaxObjects = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)ProductSKU.Length;
                Buffer.BlockCopy(ProductSKU, 0, bytes, i, ProductSKU.Length); i += ProductSKU.Length;
                bytes[i++] = (byte)ProductName.Length;
                Buffer.BlockCopy(ProductName, 0, bytes, i, ProductName.Length); i += ProductName.Length;
                Utils.UIntToBytes(MaxAgents32, bytes, i); i += 4;
                Utils.UIntToBytes(HardMaxAgents, bytes, i); i += 4;
                Utils.UIntToBytes(HardMaxObjects, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RegionInfo3Block : PacketBlock
        {
            public ulong RegionFlagsExtended;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public RegionInfo3Block() { }
            public RegionInfo3Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionFlagsExtended = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionFlagsExtended, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += RegionInfo.Length;
                length += RegionInfo2.Length;
                for (int j = 0; j < RegionInfo3.Length; j++)
                    length += RegionInfo3[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RegionInfoBlock RegionInfo;
        public RegionInfo2Block RegionInfo2;
        public RegionInfo3Block[] RegionInfo3;

        public RegionInfoPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RegionInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 142;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            RegionInfo = new RegionInfoBlock();
            RegionInfo2 = new RegionInfo2Block();
            RegionInfo3 = null;
        }

        public RegionInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RegionInfo.FromBytes(bytes, ref i);
            RegionInfo2.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RegionInfo3 == null || RegionInfo3.Length != -1) {
                RegionInfo3 = new RegionInfo3Block[count];
                for(int j = 0; j < count; j++)
                { RegionInfo3[j] = new RegionInfo3Block(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo3[j].FromBytes(bytes, ref i); }
        }

        public RegionInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RegionInfo.FromBytes(bytes, ref i);
            RegionInfo2.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RegionInfo3 == null || RegionInfo3.Length != count) {
                RegionInfo3 = new RegionInfo3Block[count];
                for(int j = 0; j < count; j++)
                { RegionInfo3[j] = new RegionInfo3Block(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo3[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RegionInfo.Length;
            length += RegionInfo2.Length;
            length++;
            for (int j = 0; j < RegionInfo3.Length; j++) { length += RegionInfo3[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RegionInfo.ToBytes(bytes, ref i);
            RegionInfo2.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RegionInfo3.Length;
            for (int j = 0; j < RegionInfo3.Length; j++) { RegionInfo3[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += RegionInfo.Length;
            fixedLength += RegionInfo2.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            RegionInfo.ToBytes(fixedBytes, ref i);
            RegionInfo2.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RegionInfo3Start = 0;
            do
            {
                int variableLength = 0;
                int RegionInfo3Count = 0;

                i = RegionInfo3Start;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RegionInfo3.Length) {
                    int blockLength = RegionInfo3[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RegionInfo3Count;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RegionInfo3Count;
                for (i = RegionInfo3Start; i < RegionInfo3Start + RegionInfo3Count; i++) { RegionInfo3[i].ToBytes(packet, ref length); }
                RegionInfo3Start += RegionInfo3Count;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RegionInfo3Start < RegionInfo3.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GodUpdateRegionInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RegionInfoBlock : PacketBlock
        {
            public byte[] SimName;
            public uint EstateID;
            public uint ParentEstateID;
            public uint RegionFlags;
            public float BillableFactor;
            public int PricePerMeter;
            public int RedirectGridX;
            public int RedirectGridY;

            public override int Length
            {
                get
                {
                    int length = 29;
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public RegionInfoBlock() { }
            public RegionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    EstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParentEstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RegionFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    BillableFactor = Utils.BytesToFloat(bytes, i); i += 4;
                    PricePerMeter = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RedirectGridX = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RedirectGridY = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                Utils.UIntToBytes(EstateID, bytes, i); i += 4;
                Utils.UIntToBytes(ParentEstateID, bytes, i); i += 4;
                Utils.UIntToBytes(RegionFlags, bytes, i); i += 4;
                Utils.FloatToBytes(BillableFactor, bytes, i); i += 4;
                Utils.IntToBytes(PricePerMeter, bytes, i); i += 4;
                Utils.IntToBytes(RedirectGridX, bytes, i); i += 4;
                Utils.IntToBytes(RedirectGridY, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RegionInfo2Block : PacketBlock
        {
            public ulong RegionFlagsExtended;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public RegionInfo2Block() { }
            public RegionInfo2Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionFlagsExtended = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionFlagsExtended, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += RegionInfo.Length;
                for (int j = 0; j < RegionInfo2.Length; j++)
                    length += RegionInfo2[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RegionInfoBlock RegionInfo;
        public RegionInfo2Block[] RegionInfo2;

        public GodUpdateRegionInfoPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GodUpdateRegionInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 143;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            RegionInfo = new RegionInfoBlock();
            RegionInfo2 = null;
        }

        public GodUpdateRegionInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RegionInfo.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RegionInfo2 == null || RegionInfo2.Length != -1) {
                RegionInfo2 = new RegionInfo2Block[count];
                for(int j = 0; j < count; j++)
                { RegionInfo2[j] = new RegionInfo2Block(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo2[j].FromBytes(bytes, ref i); }
        }

        public GodUpdateRegionInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RegionInfo.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RegionInfo2 == null || RegionInfo2.Length != count) {
                RegionInfo2 = new RegionInfo2Block[count];
                for(int j = 0; j < count; j++)
                { RegionInfo2[j] = new RegionInfo2Block(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo2[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RegionInfo.Length;
            length++;
            for (int j = 0; j < RegionInfo2.Length; j++) { length += RegionInfo2[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RegionInfo.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RegionInfo2.Length;
            for (int j = 0; j < RegionInfo2.Length; j++) { RegionInfo2[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += RegionInfo.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            RegionInfo.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RegionInfo2Start = 0;
            do
            {
                int variableLength = 0;
                int RegionInfo2Count = 0;

                i = RegionInfo2Start;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RegionInfo2.Length) {
                    int blockLength = RegionInfo2[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RegionInfo2Count;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RegionInfo2Count;
                for (i = RegionInfo2Start; i < RegionInfo2Start + RegionInfo2Count; i++) { RegionInfo2[i].ToBytes(packet, ref length); }
                RegionInfo2Start += RegionInfo2Count;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RegionInfo2Start < RegionInfo2.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RegionHandshakePacket : Packet
    {
        /// <exclude/>
        public sealed class RegionInfoBlock : PacketBlock
        {
            public uint RegionFlags;
            public byte SimAccess;
            public byte[] SimName;
            public UUID SimOwner;
            public bool IsEstateManager;
            public float WaterHeight;
            public float BillableFactor;
            public UUID CacheID;
            public UUID TerrainBase0;
            public UUID TerrainBase1;
            public UUID TerrainBase2;
            public UUID TerrainBase3;
            public UUID TerrainDetail0;
            public UUID TerrainDetail1;
            public UUID TerrainDetail2;
            public UUID TerrainDetail3;
            public float TerrainStartHeight00;
            public float TerrainStartHeight01;
            public float TerrainStartHeight10;
            public float TerrainStartHeight11;
            public float TerrainHeightRange00;
            public float TerrainHeightRange01;
            public float TerrainHeightRange10;
            public float TerrainHeightRange11;

            public override int Length
            {
                get
                {
                    int length = 207;
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public RegionInfoBlock() { }
            public RegionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RegionFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SimAccess = (byte)bytes[i++];
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    SimOwner.FromBytes(bytes, i); i += 16;
                    IsEstateManager = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    WaterHeight = Utils.BytesToFloat(bytes, i); i += 4;
                    BillableFactor = Utils.BytesToFloat(bytes, i); i += 4;
                    CacheID.FromBytes(bytes, i); i += 16;
                    TerrainBase0.FromBytes(bytes, i); i += 16;
                    TerrainBase1.FromBytes(bytes, i); i += 16;
                    TerrainBase2.FromBytes(bytes, i); i += 16;
                    TerrainBase3.FromBytes(bytes, i); i += 16;
                    TerrainDetail0.FromBytes(bytes, i); i += 16;
                    TerrainDetail1.FromBytes(bytes, i); i += 16;
                    TerrainDetail2.FromBytes(bytes, i); i += 16;
                    TerrainDetail3.FromBytes(bytes, i); i += 16;
                    TerrainStartHeight00 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainStartHeight01 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainStartHeight10 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainStartHeight11 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainHeightRange00 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainHeightRange01 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainHeightRange10 = Utils.BytesToFloat(bytes, i); i += 4;
                    TerrainHeightRange11 = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(RegionFlags, bytes, i); i += 4;
                bytes[i++] = SimAccess;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                SimOwner.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsEstateManager) ? 1 : 0);
                Utils.FloatToBytes(WaterHeight, bytes, i); i += 4;
                Utils.FloatToBytes(BillableFactor, bytes, i); i += 4;
                CacheID.ToBytes(bytes, i); i += 16;
                TerrainBase0.ToBytes(bytes, i); i += 16;
                TerrainBase1.ToBytes(bytes, i); i += 16;
                TerrainBase2.ToBytes(bytes, i); i += 16;
                TerrainBase3.ToBytes(bytes, i); i += 16;
                TerrainDetail0.ToBytes(bytes, i); i += 16;
                TerrainDetail1.ToBytes(bytes, i); i += 16;
                TerrainDetail2.ToBytes(bytes, i); i += 16;
                TerrainDetail3.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(TerrainStartHeight00, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainStartHeight01, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainStartHeight10, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainStartHeight11, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainHeightRange00, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainHeightRange01, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainHeightRange10, bytes, i); i += 4;
                Utils.FloatToBytes(TerrainHeightRange11, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RegionInfo2Block : PacketBlock
        {
            public UUID RegionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public RegionInfo2Block() { }
            public RegionInfo2Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RegionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RegionInfo3Block : PacketBlock
        {
            public int CPUClassID;
            public int CPURatio;
            public byte[] ColoName;
            public byte[] ProductSKU;
            public byte[] ProductName;

            public override int Length
            {
                get
                {
                    int length = 11;
                    if (ColoName != null) { length += ColoName.Length; }
                    if (ProductSKU != null) { length += ProductSKU.Length; }
                    if (ProductName != null) { length += ProductName.Length; }
                    return length;
                }
            }

            public RegionInfo3Block() { }
            public RegionInfo3Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    CPUClassID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CPURatio = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ColoName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ColoName, 0, length); i += length;
                    length = bytes[i++];
                    ProductSKU = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProductSKU, 0, length); i += length;
                    length = bytes[i++];
                    ProductName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProductName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(CPUClassID, bytes, i); i += 4;
                Utils.IntToBytes(CPURatio, bytes, i); i += 4;
                bytes[i++] = (byte)ColoName.Length;
                Buffer.BlockCopy(ColoName, 0, bytes, i, ColoName.Length); i += ColoName.Length;
                bytes[i++] = (byte)ProductSKU.Length;
                Buffer.BlockCopy(ProductSKU, 0, bytes, i, ProductSKU.Length); i += ProductSKU.Length;
                bytes[i++] = (byte)ProductName.Length;
                Buffer.BlockCopy(ProductName, 0, bytes, i, ProductName.Length); i += ProductName.Length;
            }

        }

        /// <exclude/>
        public sealed class RegionInfo4Block : PacketBlock
        {
            public ulong RegionFlagsExtended;
            public ulong RegionProtocols;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public RegionInfo4Block() { }
            public RegionInfo4Block(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionFlagsExtended = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    RegionProtocols = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionFlagsExtended, bytes, i); i += 8;
                Utils.UInt64ToBytes(RegionProtocols, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += RegionInfo.Length;
                length += RegionInfo2.Length;
                length += RegionInfo3.Length;
                for (int j = 0; j < RegionInfo4.Length; j++)
                    length += RegionInfo4[j].Length;
                return length;
            }
        }
        public RegionInfoBlock RegionInfo;
        public RegionInfo2Block RegionInfo2;
        public RegionInfo3Block RegionInfo3;
        public RegionInfo4Block[] RegionInfo4;

        public RegionHandshakePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RegionHandshake;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 148;
            Header.Reliable = true;
            Header.Zerocoded = true;
            RegionInfo = new RegionInfoBlock();
            RegionInfo2 = new RegionInfo2Block();
            RegionInfo3 = new RegionInfo3Block();
            RegionInfo4 = null;
        }

        public RegionHandshakePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RegionInfo.FromBytes(bytes, ref i);
            RegionInfo2.FromBytes(bytes, ref i);
            RegionInfo3.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RegionInfo4 == null || RegionInfo4.Length != -1) {
                RegionInfo4 = new RegionInfo4Block[count];
                for(int j = 0; j < count; j++)
                { RegionInfo4[j] = new RegionInfo4Block(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo4[j].FromBytes(bytes, ref i); }
        }

        public RegionHandshakePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RegionInfo.FromBytes(bytes, ref i);
            RegionInfo2.FromBytes(bytes, ref i);
            RegionInfo3.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RegionInfo4 == null || RegionInfo4.Length != count) {
                RegionInfo4 = new RegionInfo4Block[count];
                for(int j = 0; j < count; j++)
                { RegionInfo4[j] = new RegionInfo4Block(); }
            }
            for (int j = 0; j < count; j++)
            { RegionInfo4[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += RegionInfo.Length;
            length += RegionInfo2.Length;
            length += RegionInfo3.Length;
            length++;
            for (int j = 0; j < RegionInfo4.Length; j++) { length += RegionInfo4[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RegionInfo.ToBytes(bytes, ref i);
            RegionInfo2.ToBytes(bytes, ref i);
            RegionInfo3.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RegionInfo4.Length;
            for (int j = 0; j < RegionInfo4.Length; j++) { RegionInfo4[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += RegionInfo.Length;
            fixedLength += RegionInfo2.Length;
            fixedLength += RegionInfo3.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            RegionInfo.ToBytes(fixedBytes, ref i);
            RegionInfo2.ToBytes(fixedBytes, ref i);
            RegionInfo3.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RegionInfo4Start = 0;
            do
            {
                int variableLength = 0;
                int RegionInfo4Count = 0;

                i = RegionInfo4Start;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RegionInfo4.Length) {
                    int blockLength = RegionInfo4[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RegionInfo4Count;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RegionInfo4Count;
                for (i = RegionInfo4Start; i < RegionInfo4Start + RegionInfo4Count; i++) { RegionInfo4[i].ToBytes(packet, ref length); }
                RegionInfo4Start += RegionInfo4Count;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RegionInfo4Start < RegionInfo4.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RegionHandshakeReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RegionInfoBlock : PacketBlock
        {
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public RegionInfoBlock() { }
            public RegionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += RegionInfo.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RegionInfoBlock RegionInfo;

        public RegionHandshakeReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RegionHandshakeReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 149;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            RegionInfo = new RegionInfoBlock();
        }

        public RegionHandshakeReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RegionInfo.FromBytes(bytes, ref i);
        }

        public RegionHandshakeReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RegionInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RegionInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RegionInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SimulatorViewerTimeMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class TimeInfoBlock : PacketBlock
        {
            public ulong UsecSinceStart;
            public uint SecPerDay;
            public uint SecPerYear;
            public Vector3 SunDirection;
            public float SunPhase;
            public Vector3 SunAngVelocity;

            public override int Length
            {
                get
                {
                    return 44;
                }
            }

            public TimeInfoBlock() { }
            public TimeInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    UsecSinceStart = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    SecPerDay = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SecPerYear = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SunDirection.FromBytes(bytes, i); i += 12;
                    SunPhase = Utils.BytesToFloat(bytes, i); i += 4;
                    SunAngVelocity.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(UsecSinceStart, bytes, i); i += 8;
                Utils.UIntToBytes(SecPerDay, bytes, i); i += 4;
                Utils.UIntToBytes(SecPerYear, bytes, i); i += 4;
                SunDirection.ToBytes(bytes, i); i += 12;
                Utils.FloatToBytes(SunPhase, bytes, i); i += 4;
                SunAngVelocity.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TimeInfo.Length;
                return length;
            }
        }
        public TimeInfoBlock TimeInfo;

        public SimulatorViewerTimeMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SimulatorViewerTimeMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 150;
            Header.Reliable = true;
            TimeInfo = new TimeInfoBlock();
        }

        public SimulatorViewerTimeMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TimeInfo.FromBytes(bytes, ref i);
        }

        public SimulatorViewerTimeMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TimeInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TimeInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TimeInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EnableSimulatorPacket : Packet
    {
        /// <exclude/>
        public sealed class SimulatorInfoBlock : PacketBlock
        {
            public ulong Handle;
            public uint IP;
            public ushort Port;

            public override int Length
            {
                get
                {
                    return 14;
                }
            }

            public SimulatorInfoBlock() { }
            public SimulatorInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Handle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    IP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Port = (ushort)((bytes[i++] << 8) + bytes[i++]);
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(Handle, bytes, i); i += 8;
                Utils.UIntToBytes(IP, bytes, i); i += 4;
                bytes[i++] = (byte)((Port >> 8) % 256);
                bytes[i++] = (byte)(Port % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += SimulatorInfo.Length;
                return length;
            }
        }
        public SimulatorInfoBlock SimulatorInfo;

        public EnableSimulatorPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EnableSimulator;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 151;
            Header.Reliable = true;
            SimulatorInfo = new SimulatorInfoBlock();
        }

        public EnableSimulatorPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            SimulatorInfo.FromBytes(bytes, ref i);
        }

        public EnableSimulatorPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            SimulatorInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += SimulatorInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            SimulatorInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DisableSimulatorPacket : Packet
    {
        public override int Length
        {
            get
            {
                int length = 10;
                return length;
            }
        }

        public DisableSimulatorPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DisableSimulator;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 152;
            Header.Reliable = true;
        }

        public DisableSimulatorPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
        }

        public DisableSimulatorPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TransferRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class TransferInfoBlock : PacketBlock
        {
            public UUID TransferID;
            public int ChannelType;
            public int SourceType;
            public float Priority;
            public byte[] Params;

            public override int Length
            {
                get
                {
                    int length = 30;
                    if (Params != null) { length += Params.Length; }
                    return length;
                }
            }

            public TransferInfoBlock() { }
            public TransferInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TransferID.FromBytes(bytes, i); i += 16;
                    ChannelType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SourceType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Priority = Utils.BytesToFloat(bytes, i); i += 4;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Params = new byte[length];
                    Buffer.BlockCopy(bytes, i, Params, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransferID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(ChannelType, bytes, i); i += 4;
                Utils.IntToBytes(SourceType, bytes, i); i += 4;
                Utils.FloatToBytes(Priority, bytes, i); i += 4;
                bytes[i++] = (byte)(Params.Length % 256);
                bytes[i++] = (byte)((Params.Length >> 8) % 256);
                Buffer.BlockCopy(Params, 0, bytes, i, Params.Length); i += Params.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TransferInfo.Length;
                return length;
            }
        }
        public TransferInfoBlock TransferInfo;

        public TransferRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TransferRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 153;
            Header.Reliable = true;
            Header.Zerocoded = true;
            TransferInfo = new TransferInfoBlock();
        }

        public TransferRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TransferInfo.FromBytes(bytes, ref i);
        }

        public TransferRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TransferInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TransferInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TransferInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TransferInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class TransferInfoBlock : PacketBlock
        {
            public UUID TransferID;
            public int ChannelType;
            public int TargetType;
            public int Status;
            public int Size;
            public byte[] Params;

            public override int Length
            {
                get
                {
                    int length = 34;
                    if (Params != null) { length += Params.Length; }
                    return length;
                }
            }

            public TransferInfoBlock() { }
            public TransferInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TransferID.FromBytes(bytes, i); i += 16;
                    ChannelType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TargetType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Status = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Size = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Params = new byte[length];
                    Buffer.BlockCopy(bytes, i, Params, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransferID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(ChannelType, bytes, i); i += 4;
                Utils.IntToBytes(TargetType, bytes, i); i += 4;
                Utils.IntToBytes(Status, bytes, i); i += 4;
                Utils.IntToBytes(Size, bytes, i); i += 4;
                bytes[i++] = (byte)(Params.Length % 256);
                bytes[i++] = (byte)((Params.Length >> 8) % 256);
                Buffer.BlockCopy(Params, 0, bytes, i, Params.Length); i += Params.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TransferInfo.Length;
                return length;
            }
        }
        public TransferInfoBlock TransferInfo;

        public TransferInfoPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TransferInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 154;
            Header.Reliable = true;
            Header.Zerocoded = true;
            TransferInfo = new TransferInfoBlock();
        }

        public TransferInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TransferInfo.FromBytes(bytes, ref i);
        }

        public TransferInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TransferInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TransferInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TransferInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TransferAbortPacket : Packet
    {
        /// <exclude/>
        public sealed class TransferInfoBlock : PacketBlock
        {
            public UUID TransferID;
            public int ChannelType;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public TransferInfoBlock() { }
            public TransferInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransferID.FromBytes(bytes, i); i += 16;
                    ChannelType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransferID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(ChannelType, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TransferInfo.Length;
                return length;
            }
        }
        public TransferInfoBlock TransferInfo;

        public TransferAbortPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TransferAbort;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 155;
            Header.Reliable = true;
            Header.Zerocoded = true;
            TransferInfo = new TransferInfoBlock();
        }

        public TransferAbortPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TransferInfo.FromBytes(bytes, ref i);
        }

        public TransferAbortPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TransferInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TransferInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TransferInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RequestXferPacket : Packet
    {
        /// <exclude/>
        public sealed class XferIDBlock : PacketBlock
        {
            public ulong ID;
            public byte[] Filename;
            public byte FilePath;
            public bool DeleteOnCompletion;
            public bool UseBigPackets;
            public UUID VFileID;
            public short VFileType;

            public override int Length
            {
                get
                {
                    int length = 30;
                    if (Filename != null) { length += Filename.Length; }
                    return length;
                }
            }

            public XferIDBlock() { }
            public XferIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ID = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    length = bytes[i++];
                    Filename = new byte[length];
                    Buffer.BlockCopy(bytes, i, Filename, 0, length); i += length;
                    FilePath = (byte)bytes[i++];
                    DeleteOnCompletion = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    UseBigPackets = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    VFileID.FromBytes(bytes, i); i += 16;
                    VFileType = (short)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(ID, bytes, i); i += 8;
                bytes[i++] = (byte)Filename.Length;
                Buffer.BlockCopy(Filename, 0, bytes, i, Filename.Length); i += Filename.Length;
                bytes[i++] = FilePath;
                bytes[i++] = (byte)((DeleteOnCompletion) ? 1 : 0);
                bytes[i++] = (byte)((UseBigPackets) ? 1 : 0);
                VFileID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(VFileType % 256);
                bytes[i++] = (byte)((VFileType >> 8) % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += XferID.Length;
                return length;
            }
        }
        public XferIDBlock XferID;

        public RequestXferPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RequestXfer;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 156;
            Header.Reliable = true;
            Header.Zerocoded = true;
            XferID = new XferIDBlock();
        }

        public RequestXferPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            XferID.FromBytes(bytes, ref i);
        }

        public RequestXferPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            XferID.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += XferID.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            XferID.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AbortXferPacket : Packet
    {
        /// <exclude/>
        public sealed class XferIDBlock : PacketBlock
        {
            public ulong ID;
            public int Result;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public XferIDBlock() { }
            public XferIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Result = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(ID, bytes, i); i += 8;
                Utils.IntToBytes(Result, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += XferID.Length;
                return length;
            }
        }
        public XferIDBlock XferID;

        public AbortXferPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AbortXfer;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 157;
            Header.Reliable = true;
            XferID = new XferIDBlock();
        }

        public AbortXferPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            XferID.FromBytes(bytes, ref i);
        }

        public AbortXferPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            XferID.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += XferID.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            XferID.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarAppearancePacket : Packet
    {
        /// <exclude/>
        public sealed class SenderBlock : PacketBlock
        {
            public UUID ID;
            public bool IsTrial;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public SenderBlock() { }
            public SenderBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    IsTrial = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsTrial) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public byte[] TextureEntry;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (TextureEntry != null) { length += TextureEntry.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    TextureEntry = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureEntry, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(TextureEntry.Length % 256);
                bytes[i++] = (byte)((TextureEntry.Length >> 8) % 256);
                Buffer.BlockCopy(TextureEntry, 0, bytes, i, TextureEntry.Length); i += TextureEntry.Length;
            }

        }

        /// <exclude/>
        public sealed class VisualParamBlock : PacketBlock
        {
            public byte ParamValue;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public VisualParamBlock() { }
            public VisualParamBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ParamValue = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = ParamValue;
            }

        }

        /// <exclude/>
        public sealed class AppearanceDataBlock : PacketBlock
        {
            public byte AppearanceVersion;
            public int CofVersion;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 9;
                }
            }

            public AppearanceDataBlock() { }
            public AppearanceDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AppearanceVersion = (byte)bytes[i++];
                    CofVersion = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = AppearanceVersion;
                Utils.IntToBytes(CofVersion, bytes, i); i += 4;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class AppearanceHoverBlock : PacketBlock
        {
            public Vector3 HoverHeight;

            public AppearanceHoverBlock() { }
            public AppearanceHoverBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    HoverHeight.FromBytes(bytes, i);// i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                HoverHeight.ToBytes(bytes, i);
            }
        }

        public override int Length
        {
            get
            {
                int length = 13;
                length += Sender.Length;
                length += ObjectData.Length;
                for (int j = 0; j < VisualParam.Length; j++)
                    length += VisualParam[j].Length;
                for (int j = 0; j < AppearanceData.Length; j++)
                    length += AppearanceData[j].Length;
                for (int j = 0; j < AppearanceHover.Length; j++)
                    length += AppearanceHover[j].Length;
                return length;
            }
        }
        public SenderBlock Sender;
        public ObjectDataBlock ObjectData;
        public VisualParamBlock[] VisualParam;
        public AppearanceDataBlock[] AppearanceData;
        public AppearanceHoverBlock[] AppearanceHover;

        public AvatarAppearancePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AvatarAppearance;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 158;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Sender = new SenderBlock();
            ObjectData = new ObjectDataBlock();
            VisualParam = null;
            AppearanceData = null;
            AppearanceHover = null;
        }

        public AvatarAppearancePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Sender.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(VisualParam == null || VisualParam.Length != -1) {
                VisualParam = new VisualParamBlock[count];
                for(int j = 0; j < count; j++)
                { VisualParam[j] = new VisualParamBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VisualParam[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AppearanceData == null || AppearanceData.Length != -1) {
                AppearanceData = new AppearanceDataBlock[count];
                for(int j = 0; j < count; j++)
                { AppearanceData[j] = new AppearanceDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AppearanceData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AppearanceHover == null || AppearanceHover.Length != -1) {
                AppearanceHover = new AppearanceHoverBlock[count];
                for(int j = 0; j < count; j++)
                { AppearanceHover[j] = new AppearanceHoverBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AppearanceHover[j].FromBytes(bytes, ref i); }
        }

        public AvatarAppearancePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Sender.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(VisualParam == null || VisualParam.Length != count) {
                VisualParam = new VisualParamBlock[count];
                for(int j = 0; j < count; j++)
                { VisualParam[j] = new VisualParamBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VisualParam[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AppearanceData == null || AppearanceData.Length != count) {
                AppearanceData = new AppearanceDataBlock[count];
                for(int j = 0; j < count; j++)
                { AppearanceData[j] = new AppearanceDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AppearanceData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AppearanceHover == null || AppearanceHover.Length != count) {
                AppearanceHover = new AppearanceHoverBlock[count];
                for(int j = 0; j < count; j++)
                { AppearanceHover[j] = new AppearanceHoverBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AppearanceHover[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Sender.Length;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < VisualParam.Length; j++) { length += VisualParam[j].Length; }
            length++;
            for (int j = 0; j < AppearanceData.Length; j++) { length += AppearanceData[j].Length; }
            length++;
            for (int j = 0; j < AppearanceHover.Length; j++) { length += AppearanceHover[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Sender.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)VisualParam.Length;
            for (int j = 0; j < VisualParam.Length; j++) { VisualParam[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)AppearanceData.Length;
            for (int j = 0; j < AppearanceData.Length; j++) { AppearanceData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)AppearanceHover.Length;
            for (int j = 0; j < AppearanceHover.Length; j++) { AppearanceHover[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += Sender.Length;
            fixedLength += ObjectData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            Sender.ToBytes(fixedBytes, ref i);
            ObjectData.ToBytes(fixedBytes, ref i);
            fixedLength += 3;

            int VisualParamStart = 0;
            int AppearanceDataStart = 0;
            int AppearanceHoverStart = 0;
            do
            {
                int variableLength = 0;
                int VisualParamCount = 0;
                int AppearanceDataCount = 0;
                int AppearanceHoverCount = 0;

                i = VisualParamStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < VisualParam.Length) {
                    int blockLength = VisualParam[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++VisualParamCount;
                    }
                    else { break; }
                    ++i;
                }

                i = AppearanceDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AppearanceData.Length) {
                    int blockLength = AppearanceData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AppearanceDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = AppearanceHoverStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AppearanceHover.Length) {
                    int blockLength = AppearanceHover[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AppearanceHoverCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)VisualParamCount;
                for (i = VisualParamStart; i < VisualParamStart + VisualParamCount; i++) { VisualParam[i].ToBytes(packet, ref length); }
                VisualParamStart += VisualParamCount;

                packet[length++] = (byte)AppearanceDataCount;
                for (i = AppearanceDataStart; i < AppearanceDataStart + AppearanceDataCount; i++) { AppearanceData[i].ToBytes(packet, ref length); }
                AppearanceDataStart += AppearanceDataCount;

                packet[length++] = (byte)AppearanceHoverCount;
                for (i = AppearanceHoverStart; i < AppearanceHoverStart + AppearanceHoverCount; i++) { AppearanceHover[i].ToBytes(packet, ref length); }
                AppearanceHoverStart += AppearanceHoverCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                VisualParamStart < VisualParam.Length ||
                AppearanceDataStart < AppearanceData.Length ||
                AppearanceHoverStart < AppearanceHover.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class SetFollowCamPropertiesPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class CameraPropertyBlock : PacketBlock
        {
            public int Type;
            public float Value;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public CameraPropertyBlock() { }
            public CameraPropertyBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Type = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Value = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(Type, bytes, i); i += 4;
                Utils.FloatToBytes(Value, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += ObjectData.Length;
                for (int j = 0; j < CameraProperty.Length; j++)
                    length += CameraProperty[j].Length;
                return length;
            }
        }
        public ObjectDataBlock ObjectData;
        public CameraPropertyBlock[] CameraProperty;

        public SetFollowCamPropertiesPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.SetFollowCamProperties;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 159;
            Header.Reliable = true;
            ObjectData = new ObjectDataBlock();
            CameraProperty = null;
        }

        public SetFollowCamPropertiesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(CameraProperty == null || CameraProperty.Length != -1) {
                CameraProperty = new CameraPropertyBlock[count];
                for(int j = 0; j < count; j++)
                { CameraProperty[j] = new CameraPropertyBlock(); }
            }
            for (int j = 0; j < count; j++)
            { CameraProperty[j].FromBytes(bytes, ref i); }
        }

        public SetFollowCamPropertiesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(CameraProperty == null || CameraProperty.Length != count) {
                CameraProperty = new CameraPropertyBlock[count];
                for(int j = 0; j < count; j++)
                { CameraProperty[j] = new CameraPropertyBlock(); }
            }
            for (int j = 0; j < count; j++)
            { CameraProperty[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < CameraProperty.Length; j++) { length += CameraProperty[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)CameraProperty.Length;
            for (int j = 0; j < CameraProperty.Length; j++) { CameraProperty[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += ObjectData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            ObjectData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int CameraPropertyStart = 0;
            do
            {
                int variableLength = 0;
                int CameraPropertyCount = 0;

                i = CameraPropertyStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < CameraProperty.Length) {
                    int blockLength = CameraProperty[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++CameraPropertyCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)CameraPropertyCount;
                for (i = CameraPropertyStart; i < CameraPropertyStart + CameraPropertyCount; i++) { CameraProperty[i].ToBytes(packet, ref length); }
                CameraPropertyStart += CameraPropertyCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                CameraPropertyStart < CameraProperty.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ClearFollowCamPropertiesPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ObjectData.Length;
                return length;
            }
        }
        public ObjectDataBlock ObjectData;

        public ClearFollowCamPropertiesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ClearFollowCamProperties;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 160;
            Header.Reliable = true;
            ObjectData = new ObjectDataBlock();
        }

        public ClearFollowCamPropertiesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ObjectData.FromBytes(bytes, ref i);
        }

        public ClearFollowCamPropertiesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RequestPayPricePacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ObjectData.Length;
                return length;
            }
        }
        public ObjectDataBlock ObjectData;

        public RequestPayPricePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RequestPayPrice;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 161;
            Header.Reliable = true;
            ObjectData = new ObjectDataBlock();
        }

        public RequestPayPricePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ObjectData.FromBytes(bytes, ref i);
        }

        public RequestPayPricePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PayPriceReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;
            public int DefaultPayPrice;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    DefaultPayPrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(DefaultPayPrice, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ButtonDataBlock : PacketBlock
        {
            public int PayButton;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ButtonDataBlock() { }
            public ButtonDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PayButton = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(PayButton, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += ObjectData.Length;
                for (int j = 0; j < ButtonData.Length; j++)
                    length += ButtonData[j].Length;
                return length;
            }
        }
        public ObjectDataBlock ObjectData;
        public ButtonDataBlock[] ButtonData;

        public PayPriceReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.PayPriceReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 162;
            Header.Reliable = true;
            ObjectData = new ObjectDataBlock();
            ButtonData = null;
        }

        public PayPriceReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ButtonData == null || ButtonData.Length != -1) {
                ButtonData = new ButtonDataBlock[count];
                for(int j = 0; j < count; j++)
                { ButtonData[j] = new ButtonDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ButtonData[j].FromBytes(bytes, ref i); }
        }

        public PayPriceReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ObjectData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ButtonData == null || ButtonData.Length != count) {
                ButtonData = new ButtonDataBlock[count];
                for(int j = 0; j < count; j++)
                { ButtonData[j] = new ButtonDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ButtonData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ObjectData.Length;
            length++;
            for (int j = 0; j < ButtonData.Length; j++) { length += ButtonData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ButtonData.Length;
            for (int j = 0; j < ButtonData.Length; j++) { ButtonData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += ObjectData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            ObjectData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ButtonDataStart = 0;
            do
            {
                int variableLength = 0;
                int ButtonDataCount = 0;

                i = ButtonDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ButtonData.Length) {
                    int blockLength = ButtonData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ButtonDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ButtonDataCount;
                for (i = ButtonDataStart; i < ButtonDataStart + ButtonDataCount; i++) { ButtonData[i].ToBytes(packet, ref length); }
                ButtonDataStart += ButtonDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ButtonDataStart < ButtonData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class KickUserPacket : Packet
    {
        /// <exclude/>
        public sealed class TargetBlockBlock : PacketBlock
        {
            public uint TargetIP;
            public ushort TargetPort;

            public override int Length
            {
                get
                {
                    return 6;
                }
            }

            public TargetBlockBlock() { }
            public TargetBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetIP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TargetPort = (ushort)((bytes[i++] << 8) + bytes[i++]);
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(TargetIP, bytes, i); i += 4;
                bytes[i++] = (byte)((TargetPort >> 8) % 256);
                bytes[i++] = (byte)(TargetPort % 256);
            }

        }

        /// <exclude/>
        public sealed class UserInfoBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public byte[] Reason;

            public override int Length
            {
                get
                {
                    int length = 34;
                    if (Reason != null) { length += Reason.Length; }
                    return length;
                }
            }

            public UserInfoBlock() { }
            public UserInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Reason = new byte[length];
                    Buffer.BlockCopy(bytes, i, Reason, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(Reason.Length % 256);
                bytes[i++] = (byte)((Reason.Length >> 8) % 256);
                Buffer.BlockCopy(Reason, 0, bytes, i, Reason.Length); i += Reason.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TargetBlock.Length;
                length += UserInfo.Length;
                return length;
            }
        }
        public TargetBlockBlock TargetBlock;
        public UserInfoBlock UserInfo;

        public KickUserPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.KickUser;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 163;
            Header.Reliable = true;
            TargetBlock = new TargetBlockBlock();
            UserInfo = new UserInfoBlock();
        }

        public KickUserPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TargetBlock.FromBytes(bytes, ref i);
            UserInfo.FromBytes(bytes, ref i);
        }

        public KickUserPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TargetBlock.FromBytes(bytes, ref i);
            UserInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TargetBlock.Length;
            length += UserInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TargetBlock.ToBytes(bytes, ref i);
            UserInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GodKickUserPacket : Packet
    {
        /// <exclude/>
        public sealed class UserInfoBlock : PacketBlock
        {
            public UUID GodID;
            public UUID GodSessionID;
            public UUID AgentID;
            public uint KickFlags;
            public byte[] Reason;

            public override int Length
            {
                get
                {
                    int length = 54;
                    if (Reason != null) { length += Reason.Length; }
                    return length;
                }
            }

            public UserInfoBlock() { }
            public UserInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GodID.FromBytes(bytes, i); i += 16;
                    GodSessionID.FromBytes(bytes, i); i += 16;
                    AgentID.FromBytes(bytes, i); i += 16;
                    KickFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Reason = new byte[length];
                    Buffer.BlockCopy(bytes, i, Reason, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GodID.ToBytes(bytes, i); i += 16;
                GodSessionID.ToBytes(bytes, i); i += 16;
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(KickFlags, bytes, i); i += 4;
                bytes[i++] = (byte)(Reason.Length % 256);
                bytes[i++] = (byte)((Reason.Length >> 8) % 256);
                Buffer.BlockCopy(Reason, 0, bytes, i, Reason.Length); i += Reason.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += UserInfo.Length;
                return length;
            }
        }
        public UserInfoBlock UserInfo;

        public GodKickUserPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GodKickUser;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 165;
            Header.Reliable = true;
            UserInfo = new UserInfoBlock();
        }

        public GodKickUserPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            UserInfo.FromBytes(bytes, ref i);
        }

        public GodKickUserPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            UserInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += UserInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            UserInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EjectUserPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID TargetID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public EjectUserPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EjectUser;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 167;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public EjectUserPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public EjectUserPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class FreezeUserPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID TargetID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public FreezeUserPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.FreezeUser;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 168;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public FreezeUserPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public FreezeUserPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarPropertiesRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID AvatarID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    AvatarID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                AvatarID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AvatarPropertiesRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarPropertiesRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 169;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public AvatarPropertiesRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AvatarPropertiesRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarPropertiesReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID AvatarID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    AvatarID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                AvatarID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class PropertiesDataBlock : PacketBlock
        {
            public UUID ImageID;
            public UUID FLImageID;
            public UUID PartnerID;
            public byte[] AboutText;
            public byte[] FLAboutText;
            public byte[] BornOn;
            public byte[] ProfileURL;
            public byte[] CharterMember;
            public uint Flags;

            public override int Length
            {
                get
                {
                    int length = 58;
                    if (AboutText != null) { length += AboutText.Length; }
                    if (FLAboutText != null) { length += FLAboutText.Length; }
                    if (BornOn != null) { length += BornOn.Length; }
                    if (ProfileURL != null) { length += ProfileURL.Length; }
                    if (CharterMember != null) { length += CharterMember.Length; }
                    return length;
                }
            }

            public PropertiesDataBlock() { }
            public PropertiesDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ImageID.FromBytes(bytes, i); i += 16;
                    FLImageID.FromBytes(bytes, i); i += 16;
                    PartnerID.FromBytes(bytes, i); i += 16;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    AboutText = new byte[length];
                    Buffer.BlockCopy(bytes, i, AboutText, 0, length); i += length;
                    length = bytes[i++];
                    FLAboutText = new byte[length];
                    Buffer.BlockCopy(bytes, i, FLAboutText, 0, length); i += length;
                    length = bytes[i++];
                    BornOn = new byte[length];
                    Buffer.BlockCopy(bytes, i, BornOn, 0, length); i += length;
                    length = bytes[i++];
                    ProfileURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProfileURL, 0, length); i += length;
                    length = bytes[i++];
                    CharterMember = new byte[length];
                    Buffer.BlockCopy(bytes, i, CharterMember, 0, length); i += length;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ImageID.ToBytes(bytes, i); i += 16;
                FLImageID.ToBytes(bytes, i); i += 16;
                PartnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(AboutText.Length % 256);
                bytes[i++] = (byte)((AboutText.Length >> 8) % 256);
                Buffer.BlockCopy(AboutText, 0, bytes, i, AboutText.Length); i += AboutText.Length;
                bytes[i++] = (byte)FLAboutText.Length;
                Buffer.BlockCopy(FLAboutText, 0, bytes, i, FLAboutText.Length); i += FLAboutText.Length;
                bytes[i++] = (byte)BornOn.Length;
                Buffer.BlockCopy(BornOn, 0, bytes, i, BornOn.Length); i += BornOn.Length;
                bytes[i++] = (byte)ProfileURL.Length;
                Buffer.BlockCopy(ProfileURL, 0, bytes, i, ProfileURL.Length); i += ProfileURL.Length;
                bytes[i++] = (byte)CharterMember.Length;
                Buffer.BlockCopy(CharterMember, 0, bytes, i, CharterMember.Length); i += CharterMember.Length;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += PropertiesData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public PropertiesDataBlock PropertiesData;

        public AvatarPropertiesReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarPropertiesReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 171;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            PropertiesData = new PropertiesDataBlock();
        }

        public AvatarPropertiesReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public AvatarPropertiesReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += PropertiesData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            PropertiesData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarInterestsReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID AvatarID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    AvatarID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                AvatarID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class PropertiesDataBlock : PacketBlock
        {
            public uint WantToMask;
            public byte[] WantToText;
            public uint SkillsMask;
            public byte[] SkillsText;
            public byte[] LanguagesText;

            public override int Length
            {
                get
                {
                    int length = 11;
                    if (WantToText != null) { length += WantToText.Length; }
                    if (SkillsText != null) { length += SkillsText.Length; }
                    if (LanguagesText != null) { length += LanguagesText.Length; }
                    return length;
                }
            }

            public PropertiesDataBlock() { }
            public PropertiesDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    WantToMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    WantToText = new byte[length];
                    Buffer.BlockCopy(bytes, i, WantToText, 0, length); i += length;
                    SkillsMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    SkillsText = new byte[length];
                    Buffer.BlockCopy(bytes, i, SkillsText, 0, length); i += length;
                    length = bytes[i++];
                    LanguagesText = new byte[length];
                    Buffer.BlockCopy(bytes, i, LanguagesText, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(WantToMask, bytes, i); i += 4;
                bytes[i++] = (byte)WantToText.Length;
                Buffer.BlockCopy(WantToText, 0, bytes, i, WantToText.Length); i += WantToText.Length;
                Utils.UIntToBytes(SkillsMask, bytes, i); i += 4;
                bytes[i++] = (byte)SkillsText.Length;
                Buffer.BlockCopy(SkillsText, 0, bytes, i, SkillsText.Length); i += SkillsText.Length;
                bytes[i++] = (byte)LanguagesText.Length;
                Buffer.BlockCopy(LanguagesText, 0, bytes, i, LanguagesText.Length); i += LanguagesText.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += PropertiesData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public PropertiesDataBlock PropertiesData;

        public AvatarInterestsReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarInterestsReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 172;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            PropertiesData = new PropertiesDataBlock();
        }

        public AvatarInterestsReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public AvatarInterestsReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += PropertiesData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            PropertiesData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarGroupsReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID AvatarID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    AvatarID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                AvatarID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public ulong GroupPowers;
            public bool AcceptNotices;
            public byte[] GroupTitle;
            public UUID GroupID;
            public byte[] GroupName;
            public UUID GroupInsigniaID;

            public override int Length
            {
                get
                {
                    int length = 43;
                    if (GroupTitle != null) { length += GroupTitle.Length; }
                    if (GroupName != null) { length += GroupName.Length; }
                    return length;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupPowers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    AcceptNotices = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    GroupTitle = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupTitle, 0, length); i += length;
                    GroupID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    GroupName = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupName, 0, length); i += length;
                    GroupInsigniaID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(GroupPowers, bytes, i); i += 8;
                bytes[i++] = (byte)((AcceptNotices) ? 1 : 0);
                bytes[i++] = (byte)GroupTitle.Length;
                Buffer.BlockCopy(GroupTitle, 0, bytes, i, GroupTitle.Length); i += GroupTitle.Length;
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)GroupName.Length;
                Buffer.BlockCopy(GroupName, 0, bytes, i, GroupName.Length); i += GroupName.Length;
                GroupInsigniaID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class NewGroupDataBlock : PacketBlock
        {
            public bool ListInProfile;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public NewGroupDataBlock() { }
            public NewGroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ListInProfile = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((ListInProfile) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < GroupData.Length; j++)
                    length += GroupData[j].Length;
                length += NewGroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock[] GroupData;
        public NewGroupDataBlock NewGroupData;

        public AvatarGroupsReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AvatarGroupsReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 173;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = null;
            NewGroupData = new NewGroupDataBlock();
        }

        public AvatarGroupsReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != -1) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
            NewGroupData.FromBytes(bytes, ref i);
        }

        public AvatarGroupsReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != count) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
            NewGroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += NewGroupData.Length;
            length++;
            for (int j = 0; j < GroupData.Length; j++) { length += GroupData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)GroupData.Length;
            for (int j = 0; j < GroupData.Length; j++) { GroupData[j].ToBytes(bytes, ref i); }
            NewGroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarPropertiesUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class PropertiesDataBlock : PacketBlock
        {
            public UUID ImageID;
            public UUID FLImageID;
            public byte[] AboutText;
            public byte[] FLAboutText;
            public bool AllowPublish;
            public bool MaturePublish;
            public byte[] ProfileURL;

            public override int Length
            {
                get
                {
                    int length = 38;
                    if (AboutText != null) { length += AboutText.Length; }
                    if (FLAboutText != null) { length += FLAboutText.Length; }
                    if (ProfileURL != null) { length += ProfileURL.Length; }
                    return length;
                }
            }

            public PropertiesDataBlock() { }
            public PropertiesDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ImageID.FromBytes(bytes, i); i += 16;
                    FLImageID.FromBytes(bytes, i); i += 16;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    AboutText = new byte[length];
                    Buffer.BlockCopy(bytes, i, AboutText, 0, length); i += length;
                    length = bytes[i++];
                    FLAboutText = new byte[length];
                    Buffer.BlockCopy(bytes, i, FLAboutText, 0, length); i += length;
                    AllowPublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MaturePublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    ProfileURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProfileURL, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ImageID.ToBytes(bytes, i); i += 16;
                FLImageID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(AboutText.Length % 256);
                bytes[i++] = (byte)((AboutText.Length >> 8) % 256);
                Buffer.BlockCopy(AboutText, 0, bytes, i, AboutText.Length); i += AboutText.Length;
                bytes[i++] = (byte)FLAboutText.Length;
                Buffer.BlockCopy(FLAboutText, 0, bytes, i, FLAboutText.Length); i += FLAboutText.Length;
                bytes[i++] = (byte)((AllowPublish) ? 1 : 0);
                bytes[i++] = (byte)((MaturePublish) ? 1 : 0);
                bytes[i++] = (byte)ProfileURL.Length;
                Buffer.BlockCopy(ProfileURL, 0, bytes, i, ProfileURL.Length); i += ProfileURL.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += PropertiesData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public PropertiesDataBlock PropertiesData;

        public AvatarPropertiesUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarPropertiesUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 174;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            PropertiesData = new PropertiesDataBlock();
        }

        public AvatarPropertiesUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public AvatarPropertiesUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += PropertiesData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            PropertiesData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarInterestsUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class PropertiesDataBlock : PacketBlock
        {
            public uint WantToMask;
            public byte[] WantToText;
            public uint SkillsMask;
            public byte[] SkillsText;
            public byte[] LanguagesText;

            public override int Length
            {
                get
                {
                    int length = 11;
                    if (WantToText != null) { length += WantToText.Length; }
                    if (SkillsText != null) { length += SkillsText.Length; }
                    if (LanguagesText != null) { length += LanguagesText.Length; }
                    return length;
                }
            }

            public PropertiesDataBlock() { }
            public PropertiesDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    WantToMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    WantToText = new byte[length];
                    Buffer.BlockCopy(bytes, i, WantToText, 0, length); i += length;
                    SkillsMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    SkillsText = new byte[length];
                    Buffer.BlockCopy(bytes, i, SkillsText, 0, length); i += length;
                    length = bytes[i++];
                    LanguagesText = new byte[length];
                    Buffer.BlockCopy(bytes, i, LanguagesText, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(WantToMask, bytes, i); i += 4;
                bytes[i++] = (byte)WantToText.Length;
                Buffer.BlockCopy(WantToText, 0, bytes, i, WantToText.Length); i += WantToText.Length;
                Utils.UIntToBytes(SkillsMask, bytes, i); i += 4;
                bytes[i++] = (byte)SkillsText.Length;
                Buffer.BlockCopy(SkillsText, 0, bytes, i, SkillsText.Length); i += SkillsText.Length;
                bytes[i++] = (byte)LanguagesText.Length;
                Buffer.BlockCopy(LanguagesText, 0, bytes, i, LanguagesText.Length); i += LanguagesText.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += PropertiesData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public PropertiesDataBlock PropertiesData;

        public AvatarInterestsUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarInterestsUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 175;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            PropertiesData = new PropertiesDataBlock();
        }

        public AvatarInterestsUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public AvatarInterestsUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            PropertiesData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += PropertiesData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            PropertiesData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarNotesReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID TargetID;
            public byte[] Notes;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (Notes != null) { length += Notes.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Notes = new byte[length];
                    Buffer.BlockCopy(bytes, i, Notes, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(Notes.Length % 256);
                bytes[i++] = (byte)((Notes.Length >> 8) % 256);
                Buffer.BlockCopy(Notes, 0, bytes, i, Notes.Length); i += Notes.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public AvatarNotesReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarNotesReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 176;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public AvatarNotesReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public AvatarNotesReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarNotesUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID TargetID;
            public byte[] Notes;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (Notes != null) { length += Notes.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Notes = new byte[length];
                    Buffer.BlockCopy(bytes, i, Notes, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(Notes.Length % 256);
                bytes[i++] = (byte)((Notes.Length >> 8) % 256);
                Buffer.BlockCopy(Notes, 0, bytes, i, Notes.Length); i += Notes.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public AvatarNotesUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarNotesUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 177;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public AvatarNotesUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public AvatarNotesUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarPicksReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID TargetID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    TargetID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                TargetID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID PickID;
            public byte[] PickName;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (PickName != null) { length += PickName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    PickID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    PickName = new byte[length];
                    Buffer.BlockCopy(bytes, i, PickName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                PickID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)PickName.Length;
                Buffer.BlockCopy(PickName, 0, bytes, i, PickName.Length); i += PickName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;

        public AvatarPicksReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AvatarPicksReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 178;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
        }

        public AvatarPicksReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public AvatarPicksReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class EventInfoRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EventDataBlock : PacketBlock
        {
            public uint EventID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public EventDataBlock() { }
            public EventDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += EventData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EventDataBlock EventData;

        public EventInfoRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EventInfoRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 179;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            EventData = new EventDataBlock();
        }

        public EventInfoRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public EventInfoRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += EventData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            EventData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EventInfoReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EventDataBlock : PacketBlock
        {
            public uint EventID;
            public byte[] Creator;
            public byte[] Name;
            public byte[] Category;
            public byte[] Desc;
            public byte[] Date;
            public uint DateUTC;
            public uint Duration;
            public uint Cover;
            public uint Amount;
            public byte[] SimName;
            public Vector3d GlobalPos;
            public uint EventFlags;

            public override int Length
            {
                get
                {
                    int length = 55;
                    if (Creator != null) { length += Creator.Length; }
                    if (Name != null) { length += Name.Length; }
                    if (Category != null) { length += Category.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (Date != null) { length += Date.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public EventDataBlock() { }
            public EventDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Creator = new byte[length];
                    Buffer.BlockCopy(bytes, i, Creator, 0, length); i += length;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Category = new byte[length];
                    Buffer.BlockCopy(bytes, i, Category, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    length = bytes[i++];
                    Date = new byte[length];
                    Buffer.BlockCopy(bytes, i, Date, 0, length); i += length;
                    DateUTC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Duration = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Cover = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Amount = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    GlobalPos.FromBytes(bytes, i); i += 24;
                    EventFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
                bytes[i++] = (byte)Creator.Length;
                Buffer.BlockCopy(Creator, 0, bytes, i, Creator.Length); i += Creator.Length;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Category.Length;
                Buffer.BlockCopy(Category, 0, bytes, i, Category.Length); i += Category.Length;
                bytes[i++] = (byte)(Desc.Length % 256);
                bytes[i++] = (byte)((Desc.Length >> 8) % 256);
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                bytes[i++] = (byte)Date.Length;
                Buffer.BlockCopy(Date, 0, bytes, i, Date.Length); i += Date.Length;
                Utils.UIntToBytes(DateUTC, bytes, i); i += 4;
                Utils.UIntToBytes(Duration, bytes, i); i += 4;
                Utils.UIntToBytes(Cover, bytes, i); i += 4;
                Utils.UIntToBytes(Amount, bytes, i); i += 4;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                GlobalPos.ToBytes(bytes, i); i += 24;
                Utils.UIntToBytes(EventFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += EventData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EventDataBlock EventData;

        public EventInfoReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EventInfoReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 180;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            EventData = new EventDataBlock();
        }

        public EventInfoReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public EventInfoReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += EventData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            EventData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EventNotificationAddRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EventDataBlock : PacketBlock
        {
            public uint EventID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public EventDataBlock() { }
            public EventDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += EventData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EventDataBlock EventData;

        public EventNotificationAddRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EventNotificationAddRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 181;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            EventData = new EventDataBlock();
        }

        public EventNotificationAddRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public EventNotificationAddRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += EventData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            EventData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EventNotificationRemoveRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EventDataBlock : PacketBlock
        {
            public uint EventID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public EventDataBlock() { }
            public EventDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += EventData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EventDataBlock EventData;

        public EventNotificationRemoveRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EventNotificationRemoveRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 182;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            EventData = new EventDataBlock();
        }

        public EventNotificationRemoveRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public EventNotificationRemoveRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += EventData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            EventData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EventGodDeletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EventDataBlock : PacketBlock
        {
            public uint EventID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public EventDataBlock() { }
            public EventDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class QueryDataBlock : PacketBlock
        {
            public UUID QueryID;
            public byte[] QueryText;
            public uint QueryFlags;
            public int QueryStart;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (QueryText != null) { length += QueryText.Length; }
                    return length;
                }
            }

            public QueryDataBlock() { }
            public QueryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    QueryID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    QueryText = new byte[length];
                    Buffer.BlockCopy(bytes, i, QueryText, 0, length); i += length;
                    QueryFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    QueryStart = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                QueryID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)QueryText.Length;
                Buffer.BlockCopy(QueryText, 0, bytes, i, QueryText.Length); i += QueryText.Length;
                Utils.UIntToBytes(QueryFlags, bytes, i); i += 4;
                Utils.IntToBytes(QueryStart, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += EventData.Length;
                length += QueryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EventDataBlock EventData;
        public QueryDataBlock QueryData;

        public EventGodDeletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EventGodDelete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 183;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            EventData = new EventDataBlock();
            QueryData = new QueryDataBlock();
        }

        public EventGodDeletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public EventGodDeletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
            QueryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += EventData.Length;
            length += QueryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            EventData.ToBytes(bytes, ref i);
            QueryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PickInfoReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID PickID;
            public UUID CreatorID;
            public bool TopPick;
            public UUID ParcelID;
            public byte[] Name;
            public byte[] Desc;
            public UUID SnapshotID;
            public byte[] User;
            public byte[] OriginalName;
            public byte[] SimName;
            public Vector3d PosGlobal;
            public int SortOrder;
            public bool Enabled;

            public override int Length
            {
                get
                {
                    int length = 100;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (User != null) { length += User.Length; }
                    if (OriginalName != null) { length += OriginalName.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    PickID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    TopPick = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ParcelID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    User = new byte[length];
                    Buffer.BlockCopy(bytes, i, User, 0, length); i += length;
                    length = bytes[i++];
                    OriginalName = new byte[length];
                    Buffer.BlockCopy(bytes, i, OriginalName, 0, length); i += length;
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    PosGlobal.FromBytes(bytes, i); i += 24;
                    SortOrder = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Enabled = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                PickID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((TopPick) ? 1 : 0);
                ParcelID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)(Desc.Length % 256);
                bytes[i++] = (byte)((Desc.Length >> 8) % 256);
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                SnapshotID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)User.Length;
                Buffer.BlockCopy(User, 0, bytes, i, User.Length); i += User.Length;
                bytes[i++] = (byte)OriginalName.Length;
                Buffer.BlockCopy(OriginalName, 0, bytes, i, OriginalName.Length); i += OriginalName.Length;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                PosGlobal.ToBytes(bytes, i); i += 24;
                Utils.IntToBytes(SortOrder, bytes, i); i += 4;
                bytes[i++] = (byte)((Enabled) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public PickInfoReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.PickInfoReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 184;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public PickInfoReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public PickInfoReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PickInfoUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID PickID;
            public UUID CreatorID;
            public bool TopPick;
            public UUID ParcelID;
            public byte[] Name;
            public byte[] Desc;
            public UUID SnapshotID;
            public Vector3d PosGlobal;
            public int SortOrder;
            public bool Enabled;

            public override int Length
            {
                get
                {
                    int length = 97;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    PickID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    TopPick = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ParcelID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    PosGlobal.FromBytes(bytes, i); i += 24;
                    SortOrder = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Enabled = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                PickID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((TopPick) ? 1 : 0);
                ParcelID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)(Desc.Length % 256);
                bytes[i++] = (byte)((Desc.Length >> 8) % 256);
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                SnapshotID.ToBytes(bytes, i); i += 16;
                PosGlobal.ToBytes(bytes, i); i += 24;
                Utils.IntToBytes(SortOrder, bytes, i); i += 4;
                bytes[i++] = (byte)((Enabled) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public PickInfoUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.PickInfoUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 185;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public PickInfoUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public PickInfoUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PickDeletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID PickID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PickID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                PickID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public PickDeletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.PickDelete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 186;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public PickDeletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public PickDeletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PickGodDeletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID PickID;
            public UUID QueryID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PickID.FromBytes(bytes, i); i += 16;
                    QueryID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                PickID.ToBytes(bytes, i); i += 16;
                QueryID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public PickGodDeletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.PickGodDelete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 187;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public PickGodDeletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public PickGodDeletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptQuestionPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID TaskID;
            public UUID ItemID;
            public byte[] ObjectName;
            public byte[] ObjectOwner;
            public int Questions;

            public override int Length
            {
                get
                {
                    int length = 38;
                    if (ObjectName != null) { length += ObjectName.Length; }
                    if (ObjectOwner != null) { length += ObjectOwner.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TaskID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    ObjectName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectName, 0, length); i += length;
                    length = bytes[i++];
                    ObjectOwner = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectOwner, 0, length); i += length;
                    Questions = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TaskID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)ObjectName.Length;
                Buffer.BlockCopy(ObjectName, 0, bytes, i, ObjectName.Length); i += ObjectName.Length;
                bytes[i++] = (byte)ObjectOwner.Length;
                Buffer.BlockCopy(ObjectOwner, 0, bytes, i, ObjectOwner.Length); i += ObjectOwner.Length;
                Utils.IntToBytes(Questions, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Data.Length;
                return length;
            }
        }
        public DataBlock Data;

        public ScriptQuestionPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptQuestion;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 188;
            Header.Reliable = true;
            Data = new DataBlock();
        }

        public ScriptQuestionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
        }

        public ScriptQuestionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptControlChangePacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public bool TakeControls;
            public uint Controls;
            public bool PassToAgent;

            public override int Length
            {
                get
                {
                    return 6;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TakeControls = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Controls = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PassToAgent = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((TakeControls) ? 1 : 0);
                Utils.UIntToBytes(Controls, bytes, i); i += 4;
                bytes[i++] = (byte)((PassToAgent) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public DataBlock[] Data;

        public ScriptControlChangePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ScriptControlChange;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 189;
            Header.Reliable = true;
            Data = null;
        }

        public ScriptControlChangePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public ScriptControlChangePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ScriptDialogPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ObjectID;
            public byte[] FirstName;
            public byte[] LastName;
            public byte[] ObjectName;
            public byte[] Message;
            public int ChatChannel;
            public UUID ImageID;

            public override int Length
            {
                get
                {
                    int length = 41;
                    if (FirstName != null) { length += FirstName.Length; }
                    if (LastName != null) { length += LastName.Length; }
                    if (ObjectName != null) { length += ObjectName.Length; }
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    FirstName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FirstName, 0, length); i += length;
                    length = bytes[i++];
                    LastName = new byte[length];
                    Buffer.BlockCopy(bytes, i, LastName, 0, length); i += length;
                    length = bytes[i++];
                    ObjectName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectName, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    ChatChannel = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ImageID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)FirstName.Length;
                Buffer.BlockCopy(FirstName, 0, bytes, i, FirstName.Length); i += FirstName.Length;
                bytes[i++] = (byte)LastName.Length;
                Buffer.BlockCopy(LastName, 0, bytes, i, LastName.Length); i += LastName.Length;
                bytes[i++] = (byte)ObjectName.Length;
                Buffer.BlockCopy(ObjectName, 0, bytes, i, ObjectName.Length); i += ObjectName.Length;
                bytes[i++] = (byte)(Message.Length % 256);
                bytes[i++] = (byte)((Message.Length >> 8) % 256);
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                Utils.IntToBytes(ChatChannel, bytes, i); i += 4;
                ImageID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ButtonsBlock : PacketBlock
        {
            public byte[] ButtonLabel;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (ButtonLabel != null) { length += ButtonLabel.Length; }
                    return length;
                }
            }

            public ButtonsBlock() { }
            public ButtonsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    ButtonLabel = new byte[length];
                    Buffer.BlockCopy(bytes, i, ButtonLabel, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)ButtonLabel.Length;
                Buffer.BlockCopy(ButtonLabel, 0, bytes, i, ButtonLabel.Length); i += ButtonLabel.Length;
            }

        }

        /// <exclude/>
        public sealed class OwnerDataBlock : PacketBlock
        {
            public UUID OwnerID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public OwnerDataBlock() { }
            public OwnerDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += Data.Length;
                for (int j = 0; j < Buttons.Length; j++)
                    length += Buttons[j].Length;
                for (int j = 0; j < OwnerData.Length; j++)
                    length += OwnerData[j].Length;
                return length;
            }
        }
        public DataBlock Data;
        public ButtonsBlock[] Buttons;
        public OwnerDataBlock[] OwnerData;

        public ScriptDialogPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ScriptDialog;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 190;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Data = new DataBlock();
            Buttons = null;
            OwnerData = null;
        }

        public ScriptDialogPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Buttons == null || Buttons.Length != -1) {
                Buttons = new ButtonsBlock[count];
                for(int j = 0; j < count; j++)
                { Buttons[j] = new ButtonsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Buttons[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(OwnerData == null || OwnerData.Length != -1) {
                OwnerData = new OwnerDataBlock[count];
                for(int j = 0; j < count; j++)
                { OwnerData[j] = new OwnerDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { OwnerData[j].FromBytes(bytes, ref i); }
        }

        public ScriptDialogPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Buttons == null || Buttons.Length != count) {
                Buttons = new ButtonsBlock[count];
                for(int j = 0; j < count; j++)
                { Buttons[j] = new ButtonsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Buttons[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(OwnerData == null || OwnerData.Length != count) {
                OwnerData = new OwnerDataBlock[count];
                for(int j = 0; j < count; j++)
                { OwnerData[j] = new OwnerDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { OwnerData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            length++;
            for (int j = 0; j < Buttons.Length; j++) { length += Buttons[j].Length; }
            length++;
            for (int j = 0; j < OwnerData.Length; j++) { length += OwnerData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Buttons.Length;
            for (int j = 0; j < Buttons.Length; j++) { Buttons[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)OwnerData.Length;
            for (int j = 0; j < OwnerData.Length; j++) { OwnerData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += Data.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            Data.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int ButtonsStart = 0;
            int OwnerDataStart = 0;
            do
            {
                int variableLength = 0;
                int ButtonsCount = 0;
                int OwnerDataCount = 0;

                i = ButtonsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Buttons.Length) {
                    int blockLength = Buttons[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ButtonsCount;
                    }
                    else { break; }
                    ++i;
                }

                i = OwnerDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < OwnerData.Length) {
                    int blockLength = OwnerData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++OwnerDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ButtonsCount;
                for (i = ButtonsStart; i < ButtonsStart + ButtonsCount; i++) { Buttons[i].ToBytes(packet, ref length); }
                ButtonsStart += ButtonsCount;

                packet[length++] = (byte)OwnerDataCount;
                for (i = OwnerDataStart; i < OwnerDataStart + OwnerDataCount; i++) { OwnerData[i].ToBytes(packet, ref length); }
                OwnerDataStart += OwnerDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ButtonsStart < Buttons.Length ||
                OwnerDataStart < OwnerData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ScriptDialogReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ObjectID;
            public int ChatChannel;
            public int ButtonIndex;
            public byte[] ButtonLabel;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (ButtonLabel != null) { length += ButtonLabel.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ChatChannel = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ButtonIndex = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ButtonLabel = new byte[length];
                    Buffer.BlockCopy(bytes, i, ButtonLabel, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(ChatChannel, bytes, i); i += 4;
                Utils.IntToBytes(ButtonIndex, bytes, i); i += 4;
                bytes[i++] = (byte)ButtonLabel.Length;
                Buffer.BlockCopy(ButtonLabel, 0, bytes, i, ButtonLabel.Length); i += ButtonLabel.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ScriptDialogReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptDialogReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 191;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ScriptDialogReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ScriptDialogReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ForceScriptControlReleasePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ForceScriptControlReleasePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ForceScriptControlRelease;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 192;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public ForceScriptControlReleasePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ForceScriptControlReleasePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RevokePermissionsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ObjectID;
            public uint ObjectPermissions;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ObjectPermissions = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(ObjectPermissions, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public RevokePermissionsPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RevokePermissions;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 193;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public RevokePermissionsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public RevokePermissionsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LoadURLPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public byte[] ObjectName;
            public UUID ObjectID;
            public UUID OwnerID;
            public bool OwnerIsGroup;
            public byte[] Message;
            public byte[] URL;

            public override int Length
            {
                get
                {
                    int length = 36;
                    if (ObjectName != null) { length += ObjectName.Length; }
                    if (Message != null) { length += Message.Length; }
                    if (URL != null) { length += URL.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    ObjectName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectName, 0, length); i += length;
                    ObjectID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    OwnerIsGroup = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    length = bytes[i++];
                    URL = new byte[length];
                    Buffer.BlockCopy(bytes, i, URL, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)ObjectName.Length;
                Buffer.BlockCopy(ObjectName, 0, bytes, i, ObjectName.Length); i += ObjectName.Length;
                ObjectID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((OwnerIsGroup) ? 1 : 0);
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                bytes[i++] = (byte)URL.Length;
                Buffer.BlockCopy(URL, 0, bytes, i, URL.Length); i += URL.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Data.Length;
                return length;
            }
        }
        public DataBlock Data;

        public LoadURLPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LoadURL;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 194;
            Header.Reliable = true;
            Data = new DataBlock();
        }

        public LoadURLPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
        }

        public LoadURLPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptTeleportRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public byte[] ObjectName;
            public byte[] SimName;
            public Vector3 SimPosition;
            public Vector3 LookAt;

            public override int Length
            {
                get
                {
                    int length = 26;
                    if (ObjectName != null) { length += ObjectName.Length; }
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    ObjectName = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectName, 0, length); i += length;
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    SimPosition.FromBytes(bytes, i); i += 12;
                    LookAt.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)ObjectName.Length;
                Buffer.BlockCopy(ObjectName, 0, bytes, i, ObjectName.Length); i += ObjectName.Length;
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                SimPosition.ToBytes(bytes, i); i += 12;
                LookAt.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Data.Length;
                return length;
            }
        }
        public DataBlock Data;

        public ScriptTeleportRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptTeleportRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 195;
            Header.Reliable = true;
            Data = new DataBlock();
        }

        public ScriptTeleportRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
        }

        public ScriptTeleportRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelOverlayPacket : Packet
    {
        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int SequenceID;
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 6;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ParcelData.Length;
                return length;
            }
        }
        public ParcelDataBlock ParcelData;

        public ParcelOverlayPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelOverlay;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 196;
            Header.Reliable = true;
            Header.Zerocoded = true;
            ParcelData = new ParcelDataBlock();
        }

        public ParcelOverlayPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelOverlayPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelPropertiesRequestByIDPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int SequenceID;
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelPropertiesRequestByIDPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelPropertiesRequestByID;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 197;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelPropertiesRequestByIDPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelPropertiesRequestByIDPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelPropertiesUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public uint Flags;
            public uint ParcelFlags;
            public int SalePrice;
            public byte[] Name;
            public byte[] Desc;
            public byte[] MusicURL;
            public byte[] MediaURL;
            public UUID MediaID;
            public byte MediaAutoScale;
            public UUID GroupID;
            public int PassPrice;
            public float PassHours;
            public byte Category;
            public UUID AuthBuyerID;
            public UUID SnapshotID;
            public Vector3 UserLocation;
            public Vector3 UserLookAt;
            public byte LandingType;

            public override int Length
            {
                get
                {
                    int length = 119;
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (MusicURL != null) { length += MusicURL.Length; }
                    if (MediaURL != null) { length += MediaURL.Length; }
                    return length;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    length = bytes[i++];
                    MusicURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MusicURL, 0, length); i += length;
                    length = bytes[i++];
                    MediaURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaURL, 0, length); i += length;
                    MediaID.FromBytes(bytes, i); i += 16;
                    MediaAutoScale = (byte)bytes[i++];
                    GroupID.FromBytes(bytes, i); i += 16;
                    PassPrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PassHours = Utils.BytesToFloat(bytes, i); i += 4;
                    Category = (byte)bytes[i++];
                    AuthBuyerID.FromBytes(bytes, i); i += 16;
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    UserLocation.FromBytes(bytes, i); i += 12;
                    UserLookAt.FromBytes(bytes, i); i += 12;
                    LandingType = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.UIntToBytes(ParcelFlags, bytes, i); i += 4;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Desc.Length;
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                bytes[i++] = (byte)MusicURL.Length;
                Buffer.BlockCopy(MusicURL, 0, bytes, i, MusicURL.Length); i += MusicURL.Length;
                bytes[i++] = (byte)MediaURL.Length;
                Buffer.BlockCopy(MediaURL, 0, bytes, i, MediaURL.Length); i += MediaURL.Length;
                MediaID.ToBytes(bytes, i); i += 16;
                bytes[i++] = MediaAutoScale;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(PassPrice, bytes, i); i += 4;
                Utils.FloatToBytes(PassHours, bytes, i); i += 4;
                bytes[i++] = Category;
                AuthBuyerID.ToBytes(bytes, i); i += 16;
                SnapshotID.ToBytes(bytes, i); i += 16;
                UserLocation.ToBytes(bytes, i); i += 12;
                UserLookAt.ToBytes(bytes, i); i += 12;
                bytes[i++] = LandingType;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelPropertiesUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelPropertiesUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 198;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelPropertiesUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelPropertiesUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelReturnObjectsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public uint ReturnType;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ReturnType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                Utils.UIntToBytes(ReturnType, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class TaskIDsBlock : PacketBlock
        {
            public UUID TaskID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TaskIDsBlock() { }
            public TaskIDsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TaskID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TaskID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class OwnerIDsBlock : PacketBlock
        {
            public UUID OwnerID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public OwnerIDsBlock() { }
            public OwnerIDsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                length += ParcelData.Length;
                for (int j = 0; j < TaskIDs.Length; j++)
                    length += TaskIDs[j].Length;
                for (int j = 0; j < OwnerIDs.Length; j++)
                    length += OwnerIDs[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;
        public TaskIDsBlock[] TaskIDs;
        public OwnerIDsBlock[] OwnerIDs;

        public ParcelReturnObjectsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelReturnObjects;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 199;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
            TaskIDs = null;
            OwnerIDs = null;
        }

        public ParcelReturnObjectsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(TaskIDs == null || TaskIDs.Length != -1) {
                TaskIDs = new TaskIDsBlock[count];
                for(int j = 0; j < count; j++)
                { TaskIDs[j] = new TaskIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { TaskIDs[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(OwnerIDs == null || OwnerIDs.Length != -1) {
                OwnerIDs = new OwnerIDsBlock[count];
                for(int j = 0; j < count; j++)
                { OwnerIDs[j] = new OwnerIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { OwnerIDs[j].FromBytes(bytes, ref i); }
        }

        public ParcelReturnObjectsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(TaskIDs == null || TaskIDs.Length != count) {
                TaskIDs = new TaskIDsBlock[count];
                for(int j = 0; j < count; j++)
                { TaskIDs[j] = new TaskIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { TaskIDs[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(OwnerIDs == null || OwnerIDs.Length != count) {
                OwnerIDs = new OwnerIDsBlock[count];
                for(int j = 0; j < count; j++)
                { OwnerIDs[j] = new OwnerIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { OwnerIDs[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            length++;
            for (int j = 0; j < TaskIDs.Length; j++) { length += TaskIDs[j].Length; }
            length++;
            for (int j = 0; j < OwnerIDs.Length; j++) { length += OwnerIDs[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)TaskIDs.Length;
            for (int j = 0; j < TaskIDs.Length; j++) { TaskIDs[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)OwnerIDs.Length;
            for (int j = 0; j < OwnerIDs.Length; j++) { OwnerIDs[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ParcelData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ParcelData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int TaskIDsStart = 0;
            int OwnerIDsStart = 0;
            do
            {
                int variableLength = 0;
                int TaskIDsCount = 0;
                int OwnerIDsCount = 0;

                i = TaskIDsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < TaskIDs.Length) {
                    int blockLength = TaskIDs[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++TaskIDsCount;
                    }
                    else { break; }
                    ++i;
                }

                i = OwnerIDsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < OwnerIDs.Length) {
                    int blockLength = OwnerIDs[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++OwnerIDsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)TaskIDsCount;
                for (i = TaskIDsStart; i < TaskIDsStart + TaskIDsCount; i++) { TaskIDs[i].ToBytes(packet, ref length); }
                TaskIDsStart += TaskIDsCount;

                packet[length++] = (byte)OwnerIDsCount;
                for (i = OwnerIDsStart; i < OwnerIDsStart + OwnerIDsCount; i++) { OwnerIDs[i].ToBytes(packet, ref length); }
                OwnerIDsStart += OwnerIDsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                TaskIDsStart < TaskIDs.Length ||
                OwnerIDsStart < OwnerIDs.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelSetOtherCleanTimePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public int OtherCleanTime;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OtherCleanTime = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                Utils.IntToBytes(OtherCleanTime, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelSetOtherCleanTimePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelSetOtherCleanTime;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 200;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelSetOtherCleanTimePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelSetOtherCleanTimePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelDisableObjectsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public uint ReturnType;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ReturnType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                Utils.UIntToBytes(ReturnType, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class TaskIDsBlock : PacketBlock
        {
            public UUID TaskID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TaskIDsBlock() { }
            public TaskIDsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TaskID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TaskID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class OwnerIDsBlock : PacketBlock
        {
            public UUID OwnerID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public OwnerIDsBlock() { }
            public OwnerIDsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                length += ParcelData.Length;
                for (int j = 0; j < TaskIDs.Length; j++)
                    length += TaskIDs[j].Length;
                for (int j = 0; j < OwnerIDs.Length; j++)
                    length += OwnerIDs[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;
        public TaskIDsBlock[] TaskIDs;
        public OwnerIDsBlock[] OwnerIDs;

        public ParcelDisableObjectsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelDisableObjects;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 201;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
            TaskIDs = null;
            OwnerIDs = null;
        }

        public ParcelDisableObjectsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(TaskIDs == null || TaskIDs.Length != -1) {
                TaskIDs = new TaskIDsBlock[count];
                for(int j = 0; j < count; j++)
                { TaskIDs[j] = new TaskIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { TaskIDs[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(OwnerIDs == null || OwnerIDs.Length != -1) {
                OwnerIDs = new OwnerIDsBlock[count];
                for(int j = 0; j < count; j++)
                { OwnerIDs[j] = new OwnerIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { OwnerIDs[j].FromBytes(bytes, ref i); }
        }

        public ParcelDisableObjectsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(TaskIDs == null || TaskIDs.Length != count) {
                TaskIDs = new TaskIDsBlock[count];
                for(int j = 0; j < count; j++)
                { TaskIDs[j] = new TaskIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { TaskIDs[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(OwnerIDs == null || OwnerIDs.Length != count) {
                OwnerIDs = new OwnerIDsBlock[count];
                for(int j = 0; j < count; j++)
                { OwnerIDs[j] = new OwnerIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { OwnerIDs[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            length++;
            for (int j = 0; j < TaskIDs.Length; j++) { length += TaskIDs[j].Length; }
            length++;
            for (int j = 0; j < OwnerIDs.Length; j++) { length += OwnerIDs[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)TaskIDs.Length;
            for (int j = 0; j < TaskIDs.Length; j++) { TaskIDs[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)OwnerIDs.Length;
            for (int j = 0; j < OwnerIDs.Length; j++) { OwnerIDs[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ParcelData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ParcelData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int TaskIDsStart = 0;
            int OwnerIDsStart = 0;
            do
            {
                int variableLength = 0;
                int TaskIDsCount = 0;
                int OwnerIDsCount = 0;

                i = TaskIDsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < TaskIDs.Length) {
                    int blockLength = TaskIDs[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++TaskIDsCount;
                    }
                    else { break; }
                    ++i;
                }

                i = OwnerIDsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < OwnerIDs.Length) {
                    int blockLength = OwnerIDs[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++OwnerIDsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)TaskIDsCount;
                for (i = TaskIDsStart; i < TaskIDsStart + TaskIDsCount; i++) { TaskIDs[i].ToBytes(packet, ref length); }
                TaskIDsStart += TaskIDsCount;

                packet[length++] = (byte)OwnerIDsCount;
                for (i = OwnerIDsStart; i < OwnerIDsStart + OwnerIDsCount; i++) { OwnerIDs[i].ToBytes(packet, ref length); }
                OwnerIDsStart += OwnerIDsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                TaskIDsStart < TaskIDs.Length ||
                OwnerIDsStart < OwnerIDs.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelSelectObjectsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public uint ReturnType;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ReturnType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                Utils.UIntToBytes(ReturnType, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ReturnIDsBlock : PacketBlock
        {
            public UUID ReturnID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ReturnIDsBlock() { }
            public ReturnIDsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ReturnID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ReturnID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += ParcelData.Length;
                for (int j = 0; j < ReturnIDs.Length; j++)
                    length += ReturnIDs[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;
        public ReturnIDsBlock[] ReturnIDs;

        public ParcelSelectObjectsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelSelectObjects;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 202;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
            ReturnIDs = null;
        }

        public ParcelSelectObjectsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ReturnIDs == null || ReturnIDs.Length != -1) {
                ReturnIDs = new ReturnIDsBlock[count];
                for(int j = 0; j < count; j++)
                { ReturnIDs[j] = new ReturnIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ReturnIDs[j].FromBytes(bytes, ref i); }
        }

        public ParcelSelectObjectsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ReturnIDs == null || ReturnIDs.Length != count) {
                ReturnIDs = new ReturnIDsBlock[count];
                for(int j = 0; j < count; j++)
                { ReturnIDs[j] = new ReturnIDsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ReturnIDs[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            length++;
            for (int j = 0; j < ReturnIDs.Length; j++) { length += ReturnIDs[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ReturnIDs.Length;
            for (int j = 0; j < ReturnIDs.Length; j++) { ReturnIDs[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += ParcelData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            ParcelData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ReturnIDsStart = 0;
            do
            {
                int variableLength = 0;
                int ReturnIDsCount = 0;

                i = ReturnIDsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ReturnIDs.Length) {
                    int blockLength = ReturnIDs[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ReturnIDsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ReturnIDsCount;
                for (i = ReturnIDsStart; i < ReturnIDsStart + ReturnIDsCount; i++) { ReturnIDs[i].ToBytes(packet, ref length); }
                ReturnIDsStart += ReturnIDsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ReturnIDsStart < ReturnIDs.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class EstateCovenantRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public EstateCovenantRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EstateCovenantRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 203;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public EstateCovenantRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public EstateCovenantRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EstateCovenantReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID CovenantID;
            public uint CovenantTimestamp;
            public byte[] EstateName;
            public UUID EstateOwnerID;

            public override int Length
            {
                get
                {
                    int length = 37;
                    if (EstateName != null) { length += EstateName.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    CovenantID.FromBytes(bytes, i); i += 16;
                    CovenantTimestamp = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    EstateName = new byte[length];
                    Buffer.BlockCopy(bytes, i, EstateName, 0, length); i += length;
                    EstateOwnerID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                CovenantID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CovenantTimestamp, bytes, i); i += 4;
                bytes[i++] = (byte)EstateName.Length;
                Buffer.BlockCopy(EstateName, 0, bytes, i, EstateName.Length); i += EstateName.Length;
                EstateOwnerID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Data.Length;
                return length;
            }
        }
        public DataBlock Data;

        public EstateCovenantReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EstateCovenantReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 204;
            Header.Reliable = true;
            Data = new DataBlock();
        }

        public EstateCovenantReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
        }

        public EstateCovenantReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ForceObjectSelectPacket : Packet
    {
        /// <exclude/>
        public sealed class HeaderBlock : PacketBlock
        {
            public bool ResetList;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public HeaderBlock() { }
            public HeaderBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ResetList = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((ResetList) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public uint LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += _Header.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public HeaderBlock _Header;
        public DataBlock[] Data;

        public ForceObjectSelectPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ForceObjectSelect;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 205;
            Header.Reliable = true;
            _Header = new HeaderBlock();
            Data = null;
        }

        public ForceObjectSelectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            _Header.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public ForceObjectSelectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            _Header.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += _Header.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            _Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += _Header.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            _Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelBuyPassPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelBuyPassPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelBuyPass;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 206;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelBuyPassPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelBuyPassPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelDeedToGroupPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupID;
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelDeedToGroupPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelDeedToGroup;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 207;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelDeedToGroupPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelDeedToGroupPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelReclaimPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelReclaimPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelReclaim;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 208;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelReclaimPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelReclaimPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelClaimPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupID;
            public bool IsGroupOwned;
            public bool Final;

            public override int Length
            {
                get
                {
                    return 18;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    IsGroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Final = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsGroupOwned) ? 1 : 0);
                bytes[i++] = (byte)((Final) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public float West;
            public float South;
            public float East;
            public float North;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    West = Utils.BytesToFloat(bytes, i); i += 4;
                    South = Utils.BytesToFloat(bytes, i); i += 4;
                    East = Utils.BytesToFloat(bytes, i); i += 4;
                    North = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.FloatToBytes(West, bytes, i); i += 4;
                Utils.FloatToBytes(South, bytes, i); i += 4;
                Utils.FloatToBytes(East, bytes, i); i += 4;
                Utils.FloatToBytes(North, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += Data.Length;
                for (int j = 0; j < ParcelData.Length; j++)
                    length += ParcelData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;
        public ParcelDataBlock[] ParcelData;

        public ParcelClaimPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelClaim;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 209;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
            ParcelData = null;
        }

        public ParcelClaimPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParcelData == null || ParcelData.Length != -1) {
                ParcelData = new ParcelDataBlock[count];
                for(int j = 0; j < count; j++)
                { ParcelData[j] = new ParcelDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParcelData[j].FromBytes(bytes, ref i); }
        }

        public ParcelClaimPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParcelData == null || ParcelData.Length != count) {
                ParcelData = new ParcelDataBlock[count];
                for(int j = 0; j < count; j++)
                { ParcelData[j] = new ParcelDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParcelData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            length++;
            for (int j = 0; j < ParcelData.Length; j++) { length += ParcelData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ParcelData.Length;
            for (int j = 0; j < ParcelData.Length; j++) { ParcelData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += Data.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            Data.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ParcelDataStart = 0;
            do
            {
                int variableLength = 0;
                int ParcelDataCount = 0;

                i = ParcelDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ParcelData.Length) {
                    int blockLength = ParcelData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ParcelDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ParcelDataCount;
                for (i = ParcelDataStart; i < ParcelDataStart + ParcelDataCount; i++) { ParcelData[i].ToBytes(packet, ref length); }
                ParcelDataStart += ParcelDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ParcelDataStart < ParcelData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelJoinPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public float West;
            public float South;
            public float East;
            public float North;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    West = Utils.BytesToFloat(bytes, i); i += 4;
                    South = Utils.BytesToFloat(bytes, i); i += 4;
                    East = Utils.BytesToFloat(bytes, i); i += 4;
                    North = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.FloatToBytes(West, bytes, i); i += 4;
                Utils.FloatToBytes(South, bytes, i); i += 4;
                Utils.FloatToBytes(East, bytes, i); i += 4;
                Utils.FloatToBytes(North, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelJoinPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelJoin;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 210;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelJoinPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelJoinPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelDividePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public float West;
            public float South;
            public float East;
            public float North;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    West = Utils.BytesToFloat(bytes, i); i += 4;
                    South = Utils.BytesToFloat(bytes, i); i += 4;
                    East = Utils.BytesToFloat(bytes, i); i += 4;
                    North = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.FloatToBytes(West, bytes, i); i += 4;
                Utils.FloatToBytes(South, bytes, i); i += 4;
                Utils.FloatToBytes(East, bytes, i); i += 4;
                Utils.FloatToBytes(North, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelDividePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelDivide;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 211;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelDividePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelDividePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelReleasePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelReleasePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelRelease;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 212;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelReleasePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelReleasePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelBuyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupID;
            public bool IsGroupOwned;
            public bool RemoveContribution;
            public int LocalID;
            public bool Final;

            public override int Length
            {
                get
                {
                    return 23;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    IsGroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RemoveContribution = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Final = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsGroupOwned) ? 1 : 0);
                bytes[i++] = (byte)((RemoveContribution) ? 1 : 0);
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                bytes[i++] = (byte)((Final) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int Price;
            public int Area;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Price = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Area = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(Price, bytes, i); i += 4;
                Utils.IntToBytes(Area, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;
        public ParcelDataBlock ParcelData;

        public ParcelBuyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelBuy;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 213;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelBuyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelBuyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelGodForceOwnerPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID OwnerID;
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelGodForceOwnerPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelGodForceOwner;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 214;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelGodForceOwnerPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelGodForceOwnerPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelAccessListRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public int SequenceID;
            public uint Flags;
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelAccessListRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelAccessListRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 215;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelAccessListRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelAccessListRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelAccessListReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID AgentID;
            public int SequenceID;
            public uint Flags;
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 28;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ListBlock : PacketBlock
        {
            public UUID ID;
            public int Time;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public ListBlock() { }
            public ListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    Time = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Time, bytes, i); i += 4;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += Data.Length;
                for (int j = 0; j < List.Length; j++)
                    length += List[j].Length;
                return length;
            }
        }
        public DataBlock Data;
        public ListBlock[] List;

        public ParcelAccessListReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelAccessListReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 216;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Data = new DataBlock();
            List = null;
        }

        public ParcelAccessListReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(List == null || List.Length != -1) {
                List = new ListBlock[count];
                for(int j = 0; j < count; j++)
                { List[j] = new ListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { List[j].FromBytes(bytes, ref i); }
        }

        public ParcelAccessListReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(List == null || List.Length != count) {
                List = new ListBlock[count];
                for(int j = 0; j < count; j++)
                { List[j] = new ListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { List[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Data.Length;
            length++;
            for (int j = 0; j < List.Length; j++) { length += List[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            bytes[i++] = (byte)List.Length;
            for (int j = 0; j < List.Length; j++) { List[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += Data.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            Data.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ListStart = 0;
            do
            {
                int variableLength = 0;
                int ListCount = 0;

                i = ListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < List.Length) {
                    int blockLength = List[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ListCount;
                for (i = ListStart; i < ListStart + ListCount; i++) { List[i].ToBytes(packet, ref length); }
                ListStart += ListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ListStart < List.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelAccessListUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public uint Flags;
            public int LocalID;
            public UUID TransactionID;
            public int SequenceID;
            public int Sections;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TransactionID.FromBytes(bytes, i); i += 16;
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Sections = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                TransactionID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                Utils.IntToBytes(Sections, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ListBlock : PacketBlock
        {
            public UUID ID;
            public int Time;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public ListBlock() { }
            public ListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    Time = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Time, bytes, i); i += 4;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += Data.Length;
                for (int j = 0; j < List.Length; j++)
                    length += List[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;
        public ListBlock[] List;

        public ParcelAccessListUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ParcelAccessListUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 217;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
            List = null;
        }

        public ParcelAccessListUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(List == null || List.Length != -1) {
                List = new ListBlock[count];
                for(int j = 0; j < count; j++)
                { List[j] = new ListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { List[j].FromBytes(bytes, ref i); }
        }

        public ParcelAccessListUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(List == null || List.Length != count) {
                List = new ListBlock[count];
                for(int j = 0; j < count; j++)
                { List[j] = new ListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { List[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            length++;
            for (int j = 0; j < List.Length; j++) { length += List[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            bytes[i++] = (byte)List.Length;
            for (int j = 0; j < List.Length; j++) { List[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += Data.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            Data.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ListStart = 0;
            do
            {
                int variableLength = 0;
                int ListCount = 0;

                i = ListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < List.Length) {
                    int blockLength = List[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ListCount;
                for (i = ListStart; i < ListStart + ListCount; i++) { List[i].ToBytes(packet, ref length); }
                ListStart += ListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ListStart < List.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ParcelDwellRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public int LocalID;
            public UUID ParcelID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                ParcelID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelDwellRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelDwellRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 218;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelDwellRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelDwellRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelDwellReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public int LocalID;
            public UUID ParcelID;
            public float Dwell;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelID.FromBytes(bytes, i); i += 16;
                    Dwell = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                ParcelID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(Dwell, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ParcelDwellReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelDwellReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 219;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ParcelDwellReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ParcelDwellReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelGodMarkAsContentPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelGodMarkAsContentPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelGodMarkAsContent;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 227;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelGodMarkAsContentPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelGodMarkAsContentPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ViewerStartAuctionPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int LocalID;
            public UUID SnapshotID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SnapshotID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                SnapshotID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ViewerStartAuctionPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ViewerStartAuction;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 228;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ViewerStartAuctionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ViewerStartAuctionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UUIDNameRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class UUIDNameBlockBlock : PacketBlock
        {
            public UUID ID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public UUIDNameBlockBlock() { }
            public UUIDNameBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < UUIDNameBlock.Length; j++)
                    length += UUIDNameBlock[j].Length;
                return length;
            }
        }
        public UUIDNameBlockBlock[] UUIDNameBlock;

        public UUIDNameRequestPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UUIDNameRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 235;
            Header.Reliable = true;
            UUIDNameBlock = null;
        }

        public UUIDNameRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != -1) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public UUIDNameRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != count) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { length += UUIDNameBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)UUIDNameBlock.Length;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { UUIDNameBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int UUIDNameBlockStart = 0;
            do
            {
                int variableLength = 0;
                int UUIDNameBlockCount = 0;

                i = UUIDNameBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < UUIDNameBlock.Length) {
                    int blockLength = UUIDNameBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++UUIDNameBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)UUIDNameBlockCount;
                for (i = UUIDNameBlockStart; i < UUIDNameBlockStart + UUIDNameBlockCount; i++) { UUIDNameBlock[i].ToBytes(packet, ref length); }
                UUIDNameBlockStart += UUIDNameBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                UUIDNameBlockStart < UUIDNameBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UUIDNameReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class UUIDNameBlockBlock : PacketBlock
        {
            public UUID ID;
            public byte[] FirstName;
            public byte[] LastName;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (FirstName != null) { length += FirstName.Length; }
                    if (LastName != null) { length += LastName.Length; }
                    return length;
                }
            }

            public UUIDNameBlockBlock() { }
            public UUIDNameBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    FirstName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FirstName, 0, length); i += length;
                    length = bytes[i++];
                    LastName = new byte[length];
                    Buffer.BlockCopy(bytes, i, LastName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)FirstName.Length;
                Buffer.BlockCopy(FirstName, 0, bytes, i, FirstName.Length); i += FirstName.Length;
                bytes[i++] = (byte)LastName.Length;
                Buffer.BlockCopy(LastName, 0, bytes, i, LastName.Length); i += LastName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < UUIDNameBlock.Length; j++)
                    length += UUIDNameBlock[j].Length;
                return length;
            }
        }
        public UUIDNameBlockBlock[] UUIDNameBlock;

        public UUIDNameReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UUIDNameReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 236;
            Header.Reliable = true;
            UUIDNameBlock = null;
        }

        public UUIDNameReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != -1) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public UUIDNameReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != count) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { length += UUIDNameBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)UUIDNameBlock.Length;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { UUIDNameBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int UUIDNameBlockStart = 0;
            do
            {
                int variableLength = 0;
                int UUIDNameBlockCount = 0;

                i = UUIDNameBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < UUIDNameBlock.Length) {
                    int blockLength = UUIDNameBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++UUIDNameBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)UUIDNameBlockCount;
                for (i = UUIDNameBlockStart; i < UUIDNameBlockStart + UUIDNameBlockCount; i++) { UUIDNameBlock[i].ToBytes(packet, ref length); }
                UUIDNameBlockStart += UUIDNameBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                UUIDNameBlockStart < UUIDNameBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UUIDGroupNameRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class UUIDNameBlockBlock : PacketBlock
        {
            public UUID ID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public UUIDNameBlockBlock() { }
            public UUIDNameBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < UUIDNameBlock.Length; j++)
                    length += UUIDNameBlock[j].Length;
                return length;
            }
        }
        public UUIDNameBlockBlock[] UUIDNameBlock;

        public UUIDGroupNameRequestPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UUIDGroupNameRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 237;
            Header.Reliable = true;
            UUIDNameBlock = null;
        }

        public UUIDGroupNameRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != -1) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public UUIDGroupNameRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != count) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { length += UUIDNameBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)UUIDNameBlock.Length;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { UUIDNameBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int UUIDNameBlockStart = 0;
            do
            {
                int variableLength = 0;
                int UUIDNameBlockCount = 0;

                i = UUIDNameBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < UUIDNameBlock.Length) {
                    int blockLength = UUIDNameBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++UUIDNameBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)UUIDNameBlockCount;
                for (i = UUIDNameBlockStart; i < UUIDNameBlockStart + UUIDNameBlockCount; i++) { UUIDNameBlock[i].ToBytes(packet, ref length); }
                UUIDNameBlockStart += UUIDNameBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                UUIDNameBlockStart < UUIDNameBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UUIDGroupNameReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class UUIDNameBlockBlock : PacketBlock
        {
            public UUID ID;
            public byte[] GroupName;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (GroupName != null) { length += GroupName.Length; }
                    return length;
                }
            }

            public UUIDNameBlockBlock() { }
            public UUIDNameBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    GroupName = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)GroupName.Length;
                Buffer.BlockCopy(GroupName, 0, bytes, i, GroupName.Length); i += GroupName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < UUIDNameBlock.Length; j++)
                    length += UUIDNameBlock[j].Length;
                return length;
            }
        }
        public UUIDNameBlockBlock[] UUIDNameBlock;

        public UUIDGroupNameReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UUIDGroupNameReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 238;
            Header.Reliable = true;
            UUIDNameBlock = null;
        }

        public UUIDGroupNameReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != -1) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public UUIDGroupNameReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(UUIDNameBlock == null || UUIDNameBlock.Length != count) {
                UUIDNameBlock = new UUIDNameBlockBlock[count];
                for(int j = 0; j < count; j++)
                { UUIDNameBlock[j] = new UUIDNameBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { UUIDNameBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { length += UUIDNameBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)UUIDNameBlock.Length;
            for (int j = 0; j < UUIDNameBlock.Length; j++) { UUIDNameBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int UUIDNameBlockStart = 0;
            do
            {
                int variableLength = 0;
                int UUIDNameBlockCount = 0;

                i = UUIDNameBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < UUIDNameBlock.Length) {
                    int blockLength = UUIDNameBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++UUIDNameBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)UUIDNameBlockCount;
                for (i = UUIDNameBlockStart; i < UUIDNameBlockStart + UUIDNameBlockCount; i++) { UUIDNameBlock[i].ToBytes(packet, ref length); }
                UUIDNameBlockStart += UUIDNameBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                UUIDNameBlockStart < UUIDNameBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ChildAgentDyingPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ChildAgentDyingPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ChildAgentDying;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 240;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
        }

        public ChildAgentDyingPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ChildAgentDyingPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ChildAgentUnknownPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ChildAgentUnknownPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ChildAgentUnknown;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 241;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public ChildAgentUnknownPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ChildAgentUnknownPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GetScriptRunningPacket : Packet
    {
        /// <exclude/>
        public sealed class ScriptBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public ScriptBlock() { }
            public ScriptBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Script.Length;
                return length;
            }
        }
        public ScriptBlock Script;

        public GetScriptRunningPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GetScriptRunning;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 243;
            Header.Reliable = true;
            Script = new ScriptBlock();
        }

        public GetScriptRunningPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Script.FromBytes(bytes, ref i);
        }

        public GetScriptRunningPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Script.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Script.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Script.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptRunningReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class ScriptBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID ItemID;
            public bool Running;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public ScriptBlock() { }
            public ScriptBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                    Running = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Running) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Script.Length;
                return length;
            }
        }
        public ScriptBlock Script;

        public ScriptRunningReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptRunningReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 244;
            Header.Reliable = true;
            Script = new ScriptBlock();
        }

        public ScriptRunningReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Script.FromBytes(bytes, ref i);
        }

        public ScriptRunningReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Script.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Script.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Script.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SetScriptRunningPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ScriptBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID ItemID;
            public bool Running;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public ScriptBlock() { }
            public ScriptBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                    Running = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Running) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Script.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ScriptBlock Script;

        public SetScriptRunningPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SetScriptRunning;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 245;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Script = new ScriptBlock();
        }

        public SetScriptRunningPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Script.FromBytes(bytes, ref i);
        }

        public SetScriptRunningPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Script.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Script.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Script.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptResetPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ScriptBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public ScriptBlock() { }
            public ScriptBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Script.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ScriptBlock Script;

        public ScriptResetPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptReset;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 246;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Script = new ScriptBlock();
        }

        public ScriptResetPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Script.FromBytes(bytes, ref i);
        }

        public ScriptResetPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Script.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Script.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Script.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptSensorRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class RequesterBlock : PacketBlock
        {
            public UUID SourceID;
            public UUID RequestID;
            public UUID SearchID;
            public Vector3 SearchPos;
            public Quaternion SearchDir;
            public byte[] SearchName;
            public int Type;
            public float Range;
            public float Arc;
            public ulong RegionHandle;
            public byte SearchRegions;

            public override int Length
            {
                get
                {
                    int length = 94;
                    if (SearchName != null) { length += SearchName.Length; }
                    return length;
                }
            }

            public RequesterBlock() { }
            public RequesterBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    SourceID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                    SearchID.FromBytes(bytes, i); i += 16;
                    SearchPos.FromBytes(bytes, i); i += 12;
                    SearchDir.FromBytes(bytes, i, true); i += 12;
                    length = bytes[i++];
                    SearchName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SearchName, 0, length); i += length;
                    Type = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Range = Utils.BytesToFloat(bytes, i); i += 4;
                    Arc = Utils.BytesToFloat(bytes, i); i += 4;
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    SearchRegions = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                SourceID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
                SearchID.ToBytes(bytes, i); i += 16;
                SearchPos.ToBytes(bytes, i); i += 12;
                SearchDir.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)SearchName.Length;
                Buffer.BlockCopy(SearchName, 0, bytes, i, SearchName.Length); i += SearchName.Length;
                Utils.IntToBytes(Type, bytes, i); i += 4;
                Utils.FloatToBytes(Range, bytes, i); i += 4;
                Utils.FloatToBytes(Arc, bytes, i); i += 4;
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = SearchRegions;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Requester.Length;
                return length;
            }
        }
        public RequesterBlock Requester;

        public ScriptSensorRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ScriptSensorRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 247;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Requester = new RequesterBlock();
        }

        public ScriptSensorRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Requester.FromBytes(bytes, ref i);
        }

        public ScriptSensorRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Requester.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Requester.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Requester.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ScriptSensorReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class RequesterBlock : PacketBlock
        {
            public UUID SourceID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public RequesterBlock() { }
            public RequesterBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SourceID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                SourceID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class SensedDataBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID OwnerID;
            public UUID GroupID;
            public Vector3 Position;
            public Vector3 Velocity;
            public Quaternion Rotation;
            public byte[] Name;
            public int Type;
            public float Range;

            public override int Length
            {
                get
                {
                    int length = 93;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public SensedDataBlock() { }
            public SensedDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    Position.FromBytes(bytes, i); i += 12;
                    Velocity.FromBytes(bytes, i); i += 12;
                    Rotation.FromBytes(bytes, i, true); i += 12;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    Type = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Range = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Position.ToBytes(bytes, i); i += 12;
                Velocity.ToBytes(bytes, i); i += 12;
                Rotation.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                Utils.IntToBytes(Type, bytes, i); i += 4;
                Utils.FloatToBytes(Range, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += Requester.Length;
                for (int j = 0; j < SensedData.Length; j++)
                    length += SensedData[j].Length;
                return length;
            }
        }
        public RequesterBlock Requester;
        public SensedDataBlock[] SensedData;

        public ScriptSensorReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ScriptSensorReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 248;
            Header.Reliable = true;
            Header.Zerocoded = true;
            Requester = new RequesterBlock();
            SensedData = null;
        }

        public ScriptSensorReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Requester.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SensedData == null || SensedData.Length != -1) {
                SensedData = new SensedDataBlock[count];
                for(int j = 0; j < count; j++)
                { SensedData[j] = new SensedDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SensedData[j].FromBytes(bytes, ref i); }
        }

        public ScriptSensorReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Requester.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(SensedData == null || SensedData.Length != count) {
                SensedData = new SensedDataBlock[count];
                for(int j = 0; j < count; j++)
                { SensedData[j] = new SensedDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { SensedData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += Requester.Length;
            length++;
            for (int j = 0; j < SensedData.Length; j++) { length += SensedData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Requester.ToBytes(bytes, ref i);
            bytes[i++] = (byte)SensedData.Length;
            for (int j = 0; j < SensedData.Length; j++) { SensedData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += Requester.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            Requester.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int SensedDataStart = 0;
            do
            {
                int variableLength = 0;
                int SensedDataCount = 0;

                i = SensedDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < SensedData.Length) {
                    int blockLength = SensedData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++SensedDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)SensedDataCount;
                for (i = SensedDataStart; i < SensedDataStart + SensedDataCount; i++) { SensedData[i].ToBytes(packet, ref length); }
                SensedDataStart += SensedDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                SensedDataStart < SensedData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class CompleteAgentMovementPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint CircuitCode;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    CircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CircuitCode, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public CompleteAgentMovementPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CompleteAgentMovement;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 249;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public CompleteAgentMovementPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public CompleteAgentMovementPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentMovementCompletePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public Vector3 Position;
            public Vector3 LookAt;
            public ulong RegionHandle;
            public uint Timestamp;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Position.FromBytes(bytes, i); i += 12;
                    LookAt.FromBytes(bytes, i); i += 12;
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Timestamp = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Position.ToBytes(bytes, i); i += 12;
                LookAt.ToBytes(bytes, i); i += 12;
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                Utils.UIntToBytes(Timestamp, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class SimDataBlock : PacketBlock
        {
            public byte[] ChannelVersion;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (ChannelVersion != null) { length += ChannelVersion.Length; }
                    return length;
                }
            }

            public SimDataBlock() { }
            public SimDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    ChannelVersion = new byte[length];
                    Buffer.BlockCopy(bytes, i, ChannelVersion, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(ChannelVersion.Length % 256);
                bytes[i++] = (byte)((ChannelVersion.Length >> 8) % 256);
                Buffer.BlockCopy(ChannelVersion, 0, bytes, i, ChannelVersion.Length); i += ChannelVersion.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                length += SimData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;
        public SimDataBlock SimData;

        public AgentMovementCompletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentMovementComplete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 250;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
            SimData = new SimDataBlock();
        }

        public AgentMovementCompletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            SimData.FromBytes(bytes, ref i);
        }

        public AgentMovementCompletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            SimData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            length += SimData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            SimData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LogoutRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public LogoutRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LogoutRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 252;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public LogoutRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public LogoutRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LogoutReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public LogoutReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.LogoutReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 253;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public LogoutReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public LogoutReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ImprovedInstantMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MessageBlockBlock : PacketBlock
        {
            public bool FromGroup;
            public UUID ToAgentID;
            public uint ParentEstateID;
            public UUID RegionID;
            public Vector3 Position;
            public byte Offline;
            public byte Dialog;
            public UUID ID;
            public uint Timestamp;
            public byte[] FromAgentName;
            public byte[] Message;
            public byte[] BinaryBucket;

            public override int Length
            {
                get
                {
                    int length = 76;
                    if (FromAgentName != null) { length += FromAgentName.Length; }
                    if (Message != null) { length += Message.Length; }
                    if (BinaryBucket != null) { length += BinaryBucket.Length; }
                    return length;
                }
            }

            public MessageBlockBlock() { }
            public MessageBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    FromGroup = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ToAgentID.FromBytes(bytes, i); i += 16;
                    ParentEstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RegionID.FromBytes(bytes, i); i += 16;
                    Position.FromBytes(bytes, i); i += 12;
                    Offline = (byte)bytes[i++];
                    Dialog = (byte)bytes[i++];
                    ID.FromBytes(bytes, i); i += 16;
                    Timestamp = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    FromAgentName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FromAgentName, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    BinaryBucket = new byte[length];
                    Buffer.BlockCopy(bytes, i, BinaryBucket, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((FromGroup) ? 1 : 0);
                ToAgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(ParentEstateID, bytes, i); i += 4;
                RegionID.ToBytes(bytes, i); i += 16;
                Position.ToBytes(bytes, i); i += 12;
                bytes[i++] = Offline;
                bytes[i++] = Dialog;
                ID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Timestamp, bytes, i); i += 4;
                bytes[i++] = (byte)FromAgentName.Length;
                Buffer.BlockCopy(FromAgentName, 0, bytes, i, FromAgentName.Length); i += FromAgentName.Length;
                bytes[i++] = (byte)(Message.Length % 256);
                bytes[i++] = (byte)((Message.Length >> 8) % 256);
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                bytes[i++] = (byte)(BinaryBucket.Length % 256);
                bytes[i++] = (byte)((BinaryBucket.Length >> 8) % 256);
                Buffer.BlockCopy(BinaryBucket, 0, bytes, i, BinaryBucket.Length); i += BinaryBucket.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MessageBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MessageBlockBlock MessageBlock;

        public ImprovedInstantMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ImprovedInstantMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 254;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MessageBlock = new MessageBlockBlock();
        }

        public ImprovedInstantMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MessageBlock.FromBytes(bytes, ref i);
        }

        public ImprovedInstantMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MessageBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MessageBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MessageBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RetrieveInstantMessagesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public RetrieveInstantMessagesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RetrieveInstantMessages;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 255;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public RetrieveInstantMessagesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public RetrieveInstantMessagesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class FindAgentPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentBlockBlock : PacketBlock
        {
            public UUID Hunter;
            public UUID Prey;
            public uint SpaceIP;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentBlockBlock() { }
            public AgentBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Hunter.FromBytes(bytes, i); i += 16;
                    Prey.FromBytes(bytes, i); i += 16;
                    SpaceIP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Hunter.ToBytes(bytes, i); i += 16;
                Prey.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(SpaceIP, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class LocationBlockBlock : PacketBlock
        {
            public double GlobalX;
            public double GlobalY;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public LocationBlockBlock() { }
            public LocationBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GlobalX = Utils.BytesToDouble(bytes, i); i += 8;
                    GlobalY = Utils.BytesToDouble(bytes, i); i += 8;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.DoubleToBytes(GlobalX, bytes, i); i += 8;
                Utils.DoubleToBytes(GlobalY, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentBlock.Length;
                for (int j = 0; j < LocationBlock.Length; j++)
                    length += LocationBlock[j].Length;
                return length;
            }
        }
        public AgentBlockBlock AgentBlock;
        public LocationBlockBlock[] LocationBlock;

        public FindAgentPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.FindAgent;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 256;
            Header.Reliable = true;
            AgentBlock = new AgentBlockBlock();
            LocationBlock = null;
        }

        public FindAgentPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(LocationBlock == null || LocationBlock.Length != -1) {
                LocationBlock = new LocationBlockBlock[count];
                for(int j = 0; j < count; j++)
                { LocationBlock[j] = new LocationBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { LocationBlock[j].FromBytes(bytes, ref i); }
        }

        public FindAgentPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(LocationBlock == null || LocationBlock.Length != count) {
                LocationBlock = new LocationBlockBlock[count];
                for(int j = 0; j < count; j++)
                { LocationBlock[j] = new LocationBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { LocationBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentBlock.Length;
            length++;
            for (int j = 0; j < LocationBlock.Length; j++) { length += LocationBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentBlock.ToBytes(bytes, ref i);
            bytes[i++] = (byte)LocationBlock.Length;
            for (int j = 0; j < LocationBlock.Length; j++) { LocationBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentBlock.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentBlock.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int LocationBlockStart = 0;
            do
            {
                int variableLength = 0;
                int LocationBlockCount = 0;

                i = LocationBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < LocationBlock.Length) {
                    int blockLength = LocationBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++LocationBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)LocationBlockCount;
                for (i = LocationBlockStart; i < LocationBlockStart + LocationBlockCount; i++) { LocationBlock[i].ToBytes(packet, ref length); }
                LocationBlockStart += LocationBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                LocationBlockStart < LocationBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RequestGodlikePowersPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RequestBlockBlock : PacketBlock
        {
            public bool Godlike;
            public UUID Token;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public RequestBlockBlock() { }
            public RequestBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Godlike = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Token.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((Godlike) ? 1 : 0);
                Token.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += RequestBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RequestBlockBlock RequestBlock;

        public RequestGodlikePowersPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RequestGodlikePowers;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 257;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RequestBlock = new RequestBlockBlock();
        }

        public RequestGodlikePowersPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RequestBlock.FromBytes(bytes, ref i);
        }

        public RequestGodlikePowersPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RequestBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RequestBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RequestBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GrantGodlikePowersPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GrantDataBlock : PacketBlock
        {
            public byte GodLevel;
            public UUID Token;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public GrantDataBlock() { }
            public GrantDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GodLevel = (byte)bytes[i++];
                    Token.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = GodLevel;
                Token.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GrantData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GrantDataBlock GrantData;

        public GrantGodlikePowersPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GrantGodlikePowers;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 258;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GrantData = new GrantDataBlock();
        }

        public GrantGodlikePowersPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GrantData.FromBytes(bytes, ref i);
        }

        public GrantGodlikePowersPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GrantData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GrantData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GrantData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GodlikeMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MethodDataBlock : PacketBlock
        {
            public byte[] Method;
            public UUID Invoice;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Method != null) { length += Method.Length; }
                    return length;
                }
            }

            public MethodDataBlock() { }
            public MethodDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Method = new byte[length];
                    Buffer.BlockCopy(bytes, i, Method, 0, length); i += length;
                    Invoice.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Method.Length;
                Buffer.BlockCopy(Method, 0, bytes, i, Method.Length); i += Method.Length;
                Invoice.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParamListBlock : PacketBlock
        {
            public byte[] Parameter;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Parameter != null) { length += Parameter.Length; }
                    return length;
                }
            }

            public ParamListBlock() { }
            public ParamListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Parameter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Parameter, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Parameter.Length;
                Buffer.BlockCopy(Parameter, 0, bytes, i, Parameter.Length); i += Parameter.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += MethodData.Length;
                for (int j = 0; j < ParamList.Length; j++)
                    length += ParamList[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MethodDataBlock MethodData;
        public ParamListBlock[] ParamList;

        public GodlikeMessagePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GodlikeMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 259;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MethodData = new MethodDataBlock();
            ParamList = null;
        }

        public GodlikeMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MethodData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParamList == null || ParamList.Length != -1) {
                ParamList = new ParamListBlock[count];
                for(int j = 0; j < count; j++)
                { ParamList[j] = new ParamListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParamList[j].FromBytes(bytes, ref i); }
        }

        public GodlikeMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MethodData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParamList == null || ParamList.Length != count) {
                ParamList = new ParamListBlock[count];
                for(int j = 0; j < count; j++)
                { ParamList[j] = new ParamListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParamList[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MethodData.Length;
            length++;
            for (int j = 0; j < ParamList.Length; j++) { length += ParamList[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MethodData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ParamList.Length;
            for (int j = 0; j < ParamList.Length; j++) { ParamList[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += MethodData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            MethodData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ParamListStart = 0;
            do
            {
                int variableLength = 0;
                int ParamListCount = 0;

                i = ParamListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ParamList.Length) {
                    int blockLength = ParamList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ParamListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ParamListCount;
                for (i = ParamListStart; i < ParamListStart + ParamListCount; i++) { ParamList[i].ToBytes(packet, ref length); }
                ParamListStart += ParamListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ParamListStart < ParamList.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class EstateOwnerMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MethodDataBlock : PacketBlock
        {
            public byte[] Method;
            public UUID Invoice;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Method != null) { length += Method.Length; }
                    return length;
                }
            }

            public MethodDataBlock() { }
            public MethodDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Method = new byte[length];
                    Buffer.BlockCopy(bytes, i, Method, 0, length); i += length;
                    Invoice.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Method.Length;
                Buffer.BlockCopy(Method, 0, bytes, i, Method.Length); i += Method.Length;
                Invoice.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParamListBlock : PacketBlock
        {
            public byte[] Parameter;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Parameter != null) { length += Parameter.Length; }
                    return length;
                }
            }

            public ParamListBlock() { }
            public ParamListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Parameter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Parameter, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Parameter.Length;
                Buffer.BlockCopy(Parameter, 0, bytes, i, Parameter.Length); i += Parameter.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += MethodData.Length;
                for (int j = 0; j < ParamList.Length; j++)
                    length += ParamList[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MethodDataBlock MethodData;
        public ParamListBlock[] ParamList;

        public EstateOwnerMessagePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.EstateOwnerMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 260;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MethodData = new MethodDataBlock();
            ParamList = null;
        }

        public EstateOwnerMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MethodData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParamList == null || ParamList.Length != -1) {
                ParamList = new ParamListBlock[count];
                for(int j = 0; j < count; j++)
                { ParamList[j] = new ParamListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParamList[j].FromBytes(bytes, ref i); }
        }

        public EstateOwnerMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MethodData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParamList == null || ParamList.Length != count) {
                ParamList = new ParamListBlock[count];
                for(int j = 0; j < count; j++)
                { ParamList[j] = new ParamListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParamList[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MethodData.Length;
            length++;
            for (int j = 0; j < ParamList.Length; j++) { length += ParamList[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MethodData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ParamList.Length;
            for (int j = 0; j < ParamList.Length; j++) { ParamList[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += MethodData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            MethodData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ParamListStart = 0;
            do
            {
                int variableLength = 0;
                int ParamListCount = 0;

                i = ParamListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ParamList.Length) {
                    int blockLength = ParamList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ParamListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ParamListCount;
                for (i = ParamListStart; i < ParamListStart + ParamListCount; i++) { ParamList[i].ToBytes(packet, ref length); }
                ParamListStart += ParamListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ParamListStart < ParamList.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GenericMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MethodDataBlock : PacketBlock
        {
            public byte[] Method;
            public UUID Invoice;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Method != null) { length += Method.Length; }
                    return length;
                }
            }

            public MethodDataBlock() { }
            public MethodDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Method = new byte[length];
                    Buffer.BlockCopy(bytes, i, Method, 0, length); i += length;
                    Invoice.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Method.Length;
                Buffer.BlockCopy(Method, 0, bytes, i, Method.Length); i += Method.Length;
                Invoice.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParamListBlock : PacketBlock
        {
            public byte[] Parameter;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Parameter != null) { length += Parameter.Length; }
                    return length;
                }
            }

            public ParamListBlock() { }
            public ParamListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Parameter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Parameter, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Parameter.Length;
                Buffer.BlockCopy(Parameter, 0, bytes, i, Parameter.Length); i += Parameter.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += MethodData.Length;
                for (int j = 0; j < ParamList.Length; j++)
                    length += ParamList[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MethodDataBlock MethodData;
        public ParamListBlock[] ParamList;

        public GenericMessagePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GenericMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 261;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MethodData = new MethodDataBlock();
            ParamList = null;
        }

        public GenericMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MethodData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParamList == null || ParamList.Length != -1) {
                ParamList = new ParamListBlock[count];
                for(int j = 0; j < count; j++)
                { ParamList[j] = new ParamListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParamList[j].FromBytes(bytes, ref i); }
        }

        public GenericMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MethodData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ParamList == null || ParamList.Length != count) {
                ParamList = new ParamListBlock[count];
                for(int j = 0; j < count; j++)
                { ParamList[j] = new ParamListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ParamList[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MethodData.Length;
            length++;
            for (int j = 0; j < ParamList.Length; j++) { length += ParamList[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MethodData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ParamList.Length;
            for (int j = 0; j < ParamList.Length; j++) { ParamList[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += MethodData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            MethodData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ParamListStart = 0;
            do
            {
                int variableLength = 0;
                int ParamListCount = 0;

                i = ParamListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ParamList.Length) {
                    int blockLength = ParamList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ParamListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ParamListCount;
                for (i = ParamListStart; i < ParamListStart + ParamListCount; i++) { ParamList[i].ToBytes(packet, ref length); }
                ParamListStart += ParamListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ParamListStart < ParamList.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class MuteListRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MuteDataBlock : PacketBlock
        {
            public uint MuteCRC;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public MuteDataBlock() { }
            public MuteDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    MuteCRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(MuteCRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MuteData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MuteDataBlock MuteData;

        public MuteListRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MuteListRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 262;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            MuteData = new MuteDataBlock();
        }

        public MuteListRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MuteData.FromBytes(bytes, ref i);
        }

        public MuteListRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MuteData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MuteData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MuteData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UpdateMuteListEntryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MuteDataBlock : PacketBlock
        {
            public UUID MuteID;
            public byte[] MuteName;
            public int MuteType;
            public uint MuteFlags;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (MuteName != null) { length += MuteName.Length; }
                    return length;
                }
            }

            public MuteDataBlock() { }
            public MuteDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    MuteID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    MuteName = new byte[length];
                    Buffer.BlockCopy(bytes, i, MuteName, 0, length); i += length;
                    MuteType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    MuteFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                MuteID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)MuteName.Length;
                Buffer.BlockCopy(MuteName, 0, bytes, i, MuteName.Length); i += MuteName.Length;
                Utils.IntToBytes(MuteType, bytes, i); i += 4;
                Utils.UIntToBytes(MuteFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MuteData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MuteDataBlock MuteData;

        public UpdateMuteListEntryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UpdateMuteListEntry;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 263;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            MuteData = new MuteDataBlock();
        }

        public UpdateMuteListEntryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MuteData.FromBytes(bytes, ref i);
        }

        public UpdateMuteListEntryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MuteData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MuteData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MuteData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RemoveMuteListEntryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MuteDataBlock : PacketBlock
        {
            public UUID MuteID;
            public byte[] MuteName;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (MuteName != null) { length += MuteName.Length; }
                    return length;
                }
            }

            public MuteDataBlock() { }
            public MuteDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    MuteID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    MuteName = new byte[length];
                    Buffer.BlockCopy(bytes, i, MuteName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                MuteID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)MuteName.Length;
                Buffer.BlockCopy(MuteName, 0, bytes, i, MuteName.Length); i += MuteName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MuteData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MuteDataBlock MuteData;

        public RemoveMuteListEntryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RemoveMuteListEntry;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 264;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            MuteData = new MuteDataBlock();
        }

        public RemoveMuteListEntryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MuteData.FromBytes(bytes, ref i);
        }

        public RemoveMuteListEntryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MuteData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MuteData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MuteData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CopyInventoryFromNotecardPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class NotecardDataBlock : PacketBlock
        {
            public UUID NotecardItemID;
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public NotecardDataBlock() { }
            public NotecardDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    NotecardItemID.FromBytes(bytes, i); i += 16;
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                NotecardItemID.ToBytes(bytes, i); i += 16;
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += NotecardData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public NotecardDataBlock NotecardData;
        public InventoryDataBlock[] InventoryData;

        public CopyInventoryFromNotecardPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.CopyInventoryFromNotecard;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 265;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            NotecardData = new NotecardDataBlock();
            InventoryData = null;
        }

        public CopyInventoryFromNotecardPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            NotecardData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public CopyInventoryFromNotecardPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            NotecardData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += NotecardData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            NotecardData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += NotecardData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            NotecardData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UpdateInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public uint CallbackID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID TransactionID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 142;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CallbackID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CallbackID, bytes, i); i += 4;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public UpdateInventoryItemPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UpdateInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 266;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public UpdateInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public UpdateInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UpdateCreateInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public bool SimApproved;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SimApproved = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((SimApproved) ? 1 : 0);
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public uint CallbackID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID AssetID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 142;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CallbackID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AssetID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CallbackID, bytes, i); i += 4;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                AssetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public UpdateCreateInventoryItemPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UpdateCreateInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 267;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public UpdateCreateInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public UpdateCreateInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class MoveInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public bool Stamp;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Stamp = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Stamp) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public byte[] NewName;

            public override int Length
            {
                get
                {
                    int length = 33;
                    if (NewName != null) { length += NewName.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    NewName = new byte[length];
                    Buffer.BlockCopy(bytes, i, NewName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)NewName.Length;
                Buffer.BlockCopy(NewName, 0, bytes, i, NewName.Length); i += NewName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public MoveInventoryItemPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MoveInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 268;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public MoveInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public MoveInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class CopyInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public uint CallbackID;
            public UUID OldAgentID;
            public UUID OldItemID;
            public UUID NewFolderID;
            public byte[] NewName;

            public override int Length
            {
                get
                {
                    int length = 53;
                    if (NewName != null) { length += NewName.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    CallbackID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OldAgentID.FromBytes(bytes, i); i += 16;
                    OldItemID.FromBytes(bytes, i); i += 16;
                    NewFolderID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    NewName = new byte[length];
                    Buffer.BlockCopy(bytes, i, NewName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(CallbackID, bytes, i); i += 4;
                OldAgentID.ToBytes(bytes, i); i += 16;
                OldItemID.ToBytes(bytes, i); i += 16;
                NewFolderID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)NewName.Length;
                Buffer.BlockCopy(NewName, 0, bytes, i, NewName.Length); i += NewName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public CopyInventoryItemPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.CopyInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 269;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public CopyInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public CopyInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RemoveInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public RemoveInventoryItemPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RemoveInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 270;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public RemoveInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public RemoveInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ChangeInventoryItemFlagsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public ChangeInventoryItemFlagsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ChangeInventoryItemFlags;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 271;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public ChangeInventoryItemFlagsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public ChangeInventoryItemFlagsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class SaveAssetIntoInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID NewAssetID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    NewAssetID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                NewAssetID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public SaveAssetIntoInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SaveAssetIntoInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 272;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public SaveAssetIntoInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public SaveAssetIntoInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CreateInventoryFolderPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;
            public UUID ParentID;
            public sbyte Type;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 34;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    ParentID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                ParentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += FolderData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FolderDataBlock FolderData;

        public CreateInventoryFolderPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CreateInventoryFolder;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 273;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FolderData = new FolderDataBlock();
        }

        public CreateInventoryFolderPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            FolderData.FromBytes(bytes, ref i);
        }

        public CreateInventoryFolderPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            FolderData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += FolderData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            FolderData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UpdateInventoryFolderPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;
            public UUID ParentID;
            public sbyte Type;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 34;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    ParentID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                ParentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FolderDataBlock[] FolderData;

        public UpdateInventoryFolderPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.UpdateInventoryFolder;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 274;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FolderData = null;
        }

        public UpdateInventoryFolderPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public UpdateInventoryFolderPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int FolderDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class MoveInventoryFolderPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public bool Stamp;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Stamp = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Stamp) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID FolderID;
            public UUID ParentID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    ParentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                ParentID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public MoveInventoryFolderPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MoveInventoryFolder;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 275;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public MoveInventoryFolderPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public MoveInventoryFolderPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RemoveInventoryFolderPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FolderDataBlock[] FolderData;

        public RemoveInventoryFolderPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RemoveInventoryFolder;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 276;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FolderData = null;
        }

        public RemoveInventoryFolderPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public RemoveInventoryFolderPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int FolderDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class FetchInventoryDescendentsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID FolderID;
            public UUID OwnerID;
            public int SortOrder;
            public bool FetchFolders;
            public bool FetchItems;

            public override int Length
            {
                get
                {
                    return 38;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    SortOrder = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    FetchFolders = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    FetchItems = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(SortOrder, bytes, i); i += 4;
                bytes[i++] = (byte)((FetchFolders) ? 1 : 0);
                bytes[i++] = (byte)((FetchItems) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public FetchInventoryDescendentsPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.FetchInventoryDescendents;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 277;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public FetchInventoryDescendentsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public FetchInventoryDescendentsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class InventoryDescendentsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID FolderID;
            public UUID OwnerID;
            public int Version;
            public int Descendents;

            public override int Length
            {
                get
                {
                    return 56;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    Version = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Descendents = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Version, bytes, i); i += 4;
                Utils.IntToBytes(Descendents, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;
            public UUID ParentID;
            public sbyte Type;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 34;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    ParentID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                ParentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        /// <exclude/>
        public sealed class ItemDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID AssetID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 138;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public ItemDataBlock() { }
            public ItemDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AssetID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                AssetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                for (int j = 0; j < ItemData.Length; j++)
                    length += ItemData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FolderDataBlock[] FolderData;
        public ItemDataBlock[] ItemData;

        public InventoryDescendentsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.InventoryDescendents;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 278;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            FolderData = null;
            ItemData = null;
        }

        public InventoryDescendentsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ItemData == null || ItemData.Length != -1) {
                ItemData = new ItemDataBlock[count];
                for(int j = 0; j < count; j++)
                { ItemData[j] = new ItemDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ItemData[j].FromBytes(bytes, ref i); }
        }

        public InventoryDescendentsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ItemData == null || ItemData.Length != count) {
                ItemData = new ItemDataBlock[count];
                for(int j = 0; j < count; j++)
                { ItemData[j] = new ItemDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ItemData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            length++;
            for (int j = 0; j < ItemData.Length; j++) { length += ItemData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)ItemData.Length;
            for (int j = 0; j < ItemData.Length; j++) { ItemData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int FolderDataStart = 0;
            int ItemDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;
                int ItemDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = ItemDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ItemData.Length) {
                    int blockLength = ItemData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ItemDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                packet[length++] = (byte)ItemDataCount;
                for (i = ItemDataStart; i < ItemDataStart + ItemDataCount; i++) { ItemData[i].ToBytes(packet, ref length); }
                ItemDataStart += ItemDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length ||
                ItemDataStart < ItemData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class FetchInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID OwnerID;
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OwnerID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OwnerID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public FetchInventoryPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.FetchInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 279;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public FetchInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public FetchInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class FetchInventoryReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID AssetID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 138;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AssetID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                AssetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock[] InventoryData;

        public FetchInventoryReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.FetchInventoryReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 280;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = null;
        }

        public FetchInventoryReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public FetchInventoryReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class BulkUpdateInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;
            public UUID ParentID;
            public sbyte Type;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 34;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    ParentID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                ParentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        /// <exclude/>
        public sealed class ItemDataBlock : PacketBlock
        {
            public UUID ItemID;
            public uint CallbackID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID AssetID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 142;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public ItemDataBlock() { }
            public ItemDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    CallbackID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AssetID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CallbackID, bytes, i); i += 4;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                AssetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                for (int j = 0; j < ItemData.Length; j++)
                    length += ItemData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FolderDataBlock[] FolderData;
        public ItemDataBlock[] ItemData;

        public BulkUpdateInventoryPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.BulkUpdateInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 281;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            FolderData = null;
            ItemData = null;
        }

        public BulkUpdateInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ItemData == null || ItemData.Length != -1) {
                ItemData = new ItemDataBlock[count];
                for(int j = 0; j < count; j++)
                { ItemData[j] = new ItemDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ItemData[j].FromBytes(bytes, ref i); }
        }

        public BulkUpdateInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ItemData == null || ItemData.Length != count) {
                ItemData = new ItemDataBlock[count];
                for(int j = 0; j < count; j++)
                { ItemData[j] = new ItemDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ItemData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            length++;
            for (int j = 0; j < ItemData.Length; j++) { length += ItemData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)ItemData.Length;
            for (int j = 0; j < ItemData.Length; j++) { ItemData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int FolderDataStart = 0;
            int ItemDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;
                int ItemDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = ItemDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ItemData.Length) {
                    int blockLength = ItemData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ItemDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                packet[length++] = (byte)ItemDataCount;
                for (i = ItemDataStart; i < ItemDataStart + ItemDataCount; i++) { ItemData[i].ToBytes(packet, ref length); }
                ItemDataStart += ItemDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length ||
                ItemDataStart < ItemData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RemoveInventoryObjectsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ItemDataBlock : PacketBlock
        {
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ItemDataBlock() { }
            public ItemDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                for (int j = 0; j < ItemData.Length; j++)
                    length += ItemData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FolderDataBlock[] FolderData;
        public ItemDataBlock[] ItemData;

        public RemoveInventoryObjectsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RemoveInventoryObjects;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 284;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FolderData = null;
            ItemData = null;
        }

        public RemoveInventoryObjectsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ItemData == null || ItemData.Length != -1) {
                ItemData = new ItemDataBlock[count];
                for(int j = 0; j < count; j++)
                { ItemData[j] = new ItemDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ItemData[j].FromBytes(bytes, ref i); }
        }

        public RemoveInventoryObjectsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(ItemData == null || ItemData.Length != count) {
                ItemData = new ItemDataBlock[count];
                for(int j = 0; j < count; j++)
                { ItemData[j] = new ItemDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ItemData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            length++;
            for (int j = 0; j < ItemData.Length; j++) { length += ItemData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)ItemData.Length;
            for (int j = 0; j < ItemData.Length; j++) { ItemData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int FolderDataStart = 0;
            int ItemDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;
                int ItemDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = ItemDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ItemData.Length) {
                    int blockLength = ItemData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ItemDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                packet[length++] = (byte)ItemDataCount;
                for (i = ItemDataStart; i < ItemDataStart + ItemDataCount; i++) { ItemData[i].ToBytes(packet, ref length); }
                ItemDataStart += ItemDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length ||
                ItemDataStart < ItemData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class PurgeInventoryDescendentsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public PurgeInventoryDescendentsPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.PurgeInventoryDescendents;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 285;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public PurgeInventoryDescendentsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public PurgeInventoryDescendentsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UpdateTaskInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class UpdateDataBlock : PacketBlock
        {
            public uint LocalID;
            public byte Key;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public UpdateDataBlock() { }
            public UpdateDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Key = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                bytes[i++] = Key;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID TransactionID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 138;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += UpdateData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public UpdateDataBlock UpdateData;
        public InventoryDataBlock InventoryData;

        public UpdateTaskInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UpdateTaskInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 286;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            UpdateData = new UpdateDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public UpdateTaskInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            UpdateData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public UpdateTaskInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            UpdateData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += UpdateData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            UpdateData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RemoveTaskInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public uint LocalID;
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public RemoveTaskInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RemoveTaskInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 287;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public RemoveTaskInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public RemoveTaskInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MoveTaskInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public uint LocalID;
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public MoveTaskInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MoveTaskInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 288;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public MoveTaskInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public MoveTaskInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RequestTaskInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public uint LocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    LocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(LocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public RequestTaskInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RequestTaskInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 289;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public RequestTaskInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public RequestTaskInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ReplyTaskInventoryPacket : Packet
    {
        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID TaskID;
            public short Serial;
            public byte[] Filename;

            public override int Length
            {
                get
                {
                    int length = 19;
                    if (Filename != null) { length += Filename.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TaskID.FromBytes(bytes, i); i += 16;
                    Serial = (short)(bytes[i++] + (bytes[i++] << 8));
                    length = bytes[i++];
                    Filename = new byte[length];
                    Buffer.BlockCopy(bytes, i, Filename, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TaskID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(Serial % 256);
                bytes[i++] = (byte)((Serial >> 8) % 256);
                bytes[i++] = (byte)Filename.Length;
                Buffer.BlockCopy(Filename, 0, bytes, i, Filename.Length); i += Filename.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += InventoryData.Length;
                return length;
            }
        }
        public InventoryDataBlock InventoryData;

        public ReplyTaskInventoryPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ReplyTaskInventory;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 290;
            Header.Reliable = true;
            Header.Zerocoded = true;
            InventoryData = new InventoryDataBlock();
        }

        public ReplyTaskInventoryPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            InventoryData.FromBytes(bytes, ref i);
        }

        public ReplyTaskInventoryPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class DeRezObjectPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class AgentBlockBlock : PacketBlock
        {
            public UUID GroupID;
            public byte Destination;
            public UUID DestinationID;
            public UUID TransactionID;
            public byte PacketCount;
            public byte PacketNumber;

            public override int Length
            {
                get
                {
                    return 51;
                }
            }

            public AgentBlockBlock() { }
            public AgentBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    Destination = (byte)bytes[i++];
                    DestinationID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    PacketCount = (byte)bytes[i++];
                    PacketNumber = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = Destination;
                DestinationID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = PacketCount;
                bytes[i++] = PacketNumber;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += AgentBlock.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public AgentBlockBlock AgentBlock;
        public ObjectDataBlock[] ObjectData;

        public DeRezObjectPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DeRezObject;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 291;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            AgentBlock = new AgentBlockBlock();
            ObjectData = null;
        }

        public DeRezObjectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            AgentBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public DeRezObjectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            AgentBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += AgentBlock.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            AgentBlock.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += AgentBlock.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            AgentBlock.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DeRezAckPacket : Packet
    {
        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;
            public bool Success;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Success = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Success) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TransactionData.Length;
                return length;
            }
        }
        public TransactionDataBlock TransactionData;

        public DeRezAckPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DeRezAck;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 292;
            Header.Reliable = true;
            TransactionData = new TransactionDataBlock();
        }

        public DeRezAckPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TransactionData.FromBytes(bytes, ref i);
        }

        public DeRezAckPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TransactionData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TransactionData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RezObjectPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RezDataBlock : PacketBlock
        {
            public UUID FromTaskID;
            public byte BypassRaycast;
            public Vector3 RayStart;
            public Vector3 RayEnd;
            public UUID RayTargetID;
            public bool RayEndIsIntersection;
            public bool RezSelected;
            public bool RemoveItem;
            public uint ItemFlags;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;

            public override int Length
            {
                get
                {
                    return 76;
                }
            }

            public RezDataBlock() { }
            public RezDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FromTaskID.FromBytes(bytes, i); i += 16;
                    BypassRaycast = (byte)bytes[i++];
                    RayStart.FromBytes(bytes, i); i += 12;
                    RayEnd.FromBytes(bytes, i); i += 12;
                    RayTargetID.FromBytes(bytes, i); i += 16;
                    RayEndIsIntersection = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RezSelected = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RemoveItem = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ItemFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FromTaskID.ToBytes(bytes, i); i += 16;
                bytes[i++] = BypassRaycast;
                RayStart.ToBytes(bytes, i); i += 12;
                RayEnd.ToBytes(bytes, i); i += 12;
                RayTargetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((RayEndIsIntersection) ? 1 : 0);
                bytes[i++] = (byte)((RezSelected) ? 1 : 0);
                bytes[i++] = (byte)((RemoveItem) ? 1 : 0);
                Utils.UIntToBytes(ItemFlags, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID TransactionID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 138;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += RezData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RezDataBlock RezData;
        public InventoryDataBlock InventoryData;

        public RezObjectPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RezObject;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 293;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            RezData = new RezDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public RezObjectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RezData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public RezObjectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RezData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RezData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RezData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RezObjectFromNotecardPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RezDataBlock : PacketBlock
        {
            public UUID FromTaskID;
            public byte BypassRaycast;
            public Vector3 RayStart;
            public Vector3 RayEnd;
            public UUID RayTargetID;
            public bool RayEndIsIntersection;
            public bool RezSelected;
            public bool RemoveItem;
            public uint ItemFlags;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;

            public override int Length
            {
                get
                {
                    return 76;
                }
            }

            public RezDataBlock() { }
            public RezDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FromTaskID.FromBytes(bytes, i); i += 16;
                    BypassRaycast = (byte)bytes[i++];
                    RayStart.FromBytes(bytes, i); i += 12;
                    RayEnd.FromBytes(bytes, i); i += 12;
                    RayTargetID.FromBytes(bytes, i); i += 16;
                    RayEndIsIntersection = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RezSelected = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RemoveItem = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    ItemFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FromTaskID.ToBytes(bytes, i); i += 16;
                bytes[i++] = BypassRaycast;
                RayStart.ToBytes(bytes, i); i += 12;
                RayEnd.ToBytes(bytes, i); i += 12;
                RayTargetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((RayEndIsIntersection) ? 1 : 0);
                bytes[i++] = (byte)((RezSelected) ? 1 : 0);
                bytes[i++] = (byte)((RemoveItem) ? 1 : 0);
                Utils.UIntToBytes(ItemFlags, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class NotecardDataBlock : PacketBlock
        {
            public UUID NotecardItemID;
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public NotecardDataBlock() { }
            public NotecardDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    NotecardItemID.FromBytes(bytes, i); i += 16;
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                NotecardItemID.ToBytes(bytes, i); i += 16;
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += RezData.Length;
                length += NotecardData.Length;
                for (int j = 0; j < InventoryData.Length; j++)
                    length += InventoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RezDataBlock RezData;
        public NotecardDataBlock NotecardData;
        public InventoryDataBlock[] InventoryData;

        public RezObjectFromNotecardPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RezObjectFromNotecard;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 294;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            RezData = new RezDataBlock();
            NotecardData = new NotecardDataBlock();
            InventoryData = null;
        }

        public RezObjectFromNotecardPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RezData.FromBytes(bytes, ref i);
            NotecardData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != -1) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public RezObjectFromNotecardPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RezData.FromBytes(bytes, ref i);
            NotecardData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InventoryData == null || InventoryData.Length != count) {
                InventoryData = new InventoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { InventoryData[j] = new InventoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InventoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RezData.Length;
            length += NotecardData.Length;
            length++;
            for (int j = 0; j < InventoryData.Length; j++) { length += InventoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RezData.ToBytes(bytes, ref i);
            NotecardData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InventoryData.Length;
            for (int j = 0; j < InventoryData.Length; j++) { InventoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += RezData.Length;
            fixedLength += NotecardData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            RezData.ToBytes(fixedBytes, ref i);
            NotecardData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InventoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int InventoryDataCount = 0;

                i = InventoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InventoryData.Length) {
                    int blockLength = InventoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InventoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InventoryDataCount;
                for (i = InventoryDataStart; i < InventoryDataStart + InventoryDataCount; i++) { InventoryData[i].ToBytes(packet, ref length); }
                InventoryDataStart += InventoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InventoryDataStart < InventoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AcceptFriendshipPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionBlockBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionBlockBlock() { }
            public TransactionBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += TransactionBlock.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionBlockBlock TransactionBlock;
        public FolderDataBlock[] FolderData;

        public AcceptFriendshipPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AcceptFriendship;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 297;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            TransactionBlock = new TransactionBlockBlock();
            FolderData = null;
        }

        public AcceptFriendshipPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public AcceptFriendshipPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionBlock.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionBlock.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += TransactionBlock.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            TransactionBlock.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int FolderDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DeclineFriendshipPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionBlockBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionBlockBlock() { }
            public TransactionBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += TransactionBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionBlockBlock TransactionBlock;

        public DeclineFriendshipPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DeclineFriendship;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 298;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            TransactionBlock = new TransactionBlockBlock();
        }

        public DeclineFriendshipPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
        }

        public DeclineFriendshipPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class TerminateFriendshipPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ExBlockBlock : PacketBlock
        {
            public UUID OtherID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ExBlockBlock() { }
            public ExBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OtherID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OtherID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ExBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ExBlockBlock ExBlock;

        public TerminateFriendshipPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TerminateFriendship;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 300;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ExBlock = new ExBlockBlock();
        }

        public TerminateFriendshipPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ExBlock.FromBytes(bytes, ref i);
        }

        public TerminateFriendshipPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ExBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ExBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ExBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class OfferCallingCardPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class AgentBlockBlock : PacketBlock
        {
            public UUID DestID;
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentBlockBlock() { }
            public AgentBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    DestID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                DestID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += AgentBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public AgentBlockBlock AgentBlock;

        public OfferCallingCardPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.OfferCallingCard;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 301;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            AgentBlock = new AgentBlockBlock();
        }

        public OfferCallingCardPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            AgentBlock.FromBytes(bytes, ref i);
        }

        public OfferCallingCardPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            AgentBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += AgentBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            AgentBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AcceptCallingCardPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionBlockBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionBlockBlock() { }
            public TransactionBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FolderDataBlock : PacketBlock
        {
            public UUID FolderID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public FolderDataBlock() { }
            public FolderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += TransactionBlock.Length;
                for (int j = 0; j < FolderData.Length; j++)
                    length += FolderData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionBlockBlock TransactionBlock;
        public FolderDataBlock[] FolderData;

        public AcceptCallingCardPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AcceptCallingCard;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 302;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            TransactionBlock = new TransactionBlockBlock();
            FolderData = null;
        }

        public AcceptCallingCardPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != -1) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public AcceptCallingCardPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(FolderData == null || FolderData.Length != count) {
                FolderData = new FolderDataBlock[count];
                for(int j = 0; j < count; j++)
                { FolderData[j] = new FolderDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { FolderData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionBlock.Length;
            length++;
            for (int j = 0; j < FolderData.Length; j++) { length += FolderData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionBlock.ToBytes(bytes, ref i);
            bytes[i++] = (byte)FolderData.Length;
            for (int j = 0; j < FolderData.Length; j++) { FolderData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += TransactionBlock.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            TransactionBlock.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int FolderDataStart = 0;
            do
            {
                int variableLength = 0;
                int FolderDataCount = 0;

                i = FolderDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < FolderData.Length) {
                    int blockLength = FolderData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++FolderDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)FolderDataCount;
                for (i = FolderDataStart; i < FolderDataStart + FolderDataCount; i++) { FolderData[i].ToBytes(packet, ref length); }
                FolderDataStart += FolderDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                FolderDataStart < FolderData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DeclineCallingCardPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionBlockBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionBlockBlock() { }
            public TransactionBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += TransactionBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionBlockBlock TransactionBlock;

        public DeclineCallingCardPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DeclineCallingCard;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 303;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            TransactionBlock = new TransactionBlockBlock();
        }

        public DeclineCallingCardPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
        }

        public DeclineCallingCardPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RezScriptPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class UpdateBlockBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public bool Enabled;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public UpdateBlockBlock() { }
            public UpdateBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Enabled = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = (byte)((Enabled) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class InventoryBlockBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID TransactionID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 138;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryBlockBlock() { }
            public InventoryBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += UpdateBlock.Length;
                length += InventoryBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public UpdateBlockBlock UpdateBlock;
        public InventoryBlockBlock InventoryBlock;

        public RezScriptPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RezScript;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 304;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            UpdateBlock = new UpdateBlockBlock();
            InventoryBlock = new InventoryBlockBlock();
        }

        public RezScriptPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            UpdateBlock.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public RezScriptPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            UpdateBlock.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += UpdateBlock.Length;
            length += InventoryBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            UpdateBlock.ToBytes(bytes, ref i);
            InventoryBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CreateInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryBlockBlock : PacketBlock
        {
            public uint CallbackID;
            public UUID FolderID;
            public UUID TransactionID;
            public uint NextOwnerMask;
            public sbyte Type;
            public sbyte InvType;
            public byte WearableType;
            public byte[] Name;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 45;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryBlockBlock() { }
            public InventoryBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    CallbackID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    FolderID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    WearableType = (byte)bytes[i++];
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(CallbackID, bytes, i); i += 4;
                FolderID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                bytes[i++] = WearableType;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryBlockBlock InventoryBlock;

        public CreateInventoryItemPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CreateInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 305;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryBlock = new InventoryBlockBlock();
        }

        public CreateInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public CreateInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CreateLandmarkForEventPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EventDataBlock : PacketBlock
        {
            public uint EventID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public EventDataBlock() { }
            public EventDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    EventID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(EventID, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class InventoryBlockBlock : PacketBlock
        {
            public UUID FolderID;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public InventoryBlockBlock() { }
            public InventoryBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    FolderID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                FolderID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += EventData.Length;
                length += InventoryBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EventDataBlock EventData;
        public InventoryBlockBlock InventoryBlock;

        public CreateLandmarkForEventPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CreateLandmarkForEvent;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 306;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            EventData = new EventDataBlock();
            InventoryBlock = new InventoryBlockBlock();
        }

        public CreateLandmarkForEventPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public CreateLandmarkForEventPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            EventData.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += EventData.Length;
            length += InventoryBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            EventData.ToBytes(bytes, ref i);
            InventoryBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RegionHandleRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class RequestBlockBlock : PacketBlock
        {
            public UUID RegionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public RequestBlockBlock() { }
            public RequestBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RegionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += RequestBlock.Length;
                return length;
            }
        }
        public RequestBlockBlock RequestBlock;

        public RegionHandleRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RegionHandleRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 309;
            Header.Reliable = true;
            RequestBlock = new RequestBlockBlock();
        }

        public RegionHandleRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RequestBlock.FromBytes(bytes, ref i);
        }

        public RegionHandleRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RequestBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += RequestBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RequestBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RegionIDAndHandleReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class ReplyBlockBlock : PacketBlock
        {
            public UUID RegionID;
            public ulong RegionHandle;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public ReplyBlockBlock() { }
            public ReplyBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionID.FromBytes(bytes, i); i += 16;
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RegionID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ReplyBlock.Length;
                return length;
            }
        }
        public ReplyBlockBlock ReplyBlock;

        public RegionIDAndHandleReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RegionIDAndHandleReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 310;
            Header.Reliable = true;
            ReplyBlock = new ReplyBlockBlock();
        }

        public RegionIDAndHandleReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ReplyBlock.FromBytes(bytes, ref i);
        }

        public RegionIDAndHandleReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ReplyBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ReplyBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ReplyBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MoneyTransferRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID SourceID;
            public UUID DestID;
            public byte Flags;
            public int Amount;
            public byte AggregatePermNextOwner;
            public byte AggregatePermInventory;
            public int TransactionType;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 44;
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    SourceID.FromBytes(bytes, i); i += 16;
                    DestID.FromBytes(bytes, i); i += 16;
                    Flags = (byte)bytes[i++];
                    Amount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AggregatePermNextOwner = (byte)bytes[i++];
                    AggregatePermInventory = (byte)bytes[i++];
                    TransactionType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                SourceID.ToBytes(bytes, i); i += 16;
                DestID.ToBytes(bytes, i); i += 16;
                bytes[i++] = Flags;
                Utils.IntToBytes(Amount, bytes, i); i += 4;
                bytes[i++] = AggregatePermNextOwner;
                bytes[i++] = AggregatePermInventory;
                Utils.IntToBytes(TransactionType, bytes, i); i += 4;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MoneyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;

        public MoneyTransferRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MoneyTransferRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 311;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
        }

        public MoneyTransferRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public MoneyTransferRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MoneyBalanceRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MoneyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;

        public MoneyBalanceRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MoneyBalanceRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 313;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
        }

        public MoneyBalanceRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public MoneyBalanceRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MoneyBalanceReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID TransactionID;
            public bool TransactionSuccess;
            public int MoneyBalance;
            public int SquareMetersCredit;
            public int SquareMetersCommitted;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 46;
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    TransactionSuccess = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MoneyBalance = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SquareMetersCredit = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SquareMetersCommitted = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((TransactionSuccess) ? 1 : 0);
                Utils.IntToBytes(MoneyBalance, bytes, i); i += 4;
                Utils.IntToBytes(SquareMetersCredit, bytes, i); i += 4;
                Utils.IntToBytes(SquareMetersCommitted, bytes, i); i += 4;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        /// <exclude/>
        public sealed class TransactionInfoBlock : PacketBlock
        {
            public int TransactionType;
            public UUID SourceID;
            public bool IsSourceGroup;
            public UUID DestID;
            public bool IsDestGroup;
            public int Amount;
            public byte[] ItemDescription;

            public override int Length
            {
                get
                {
                    int length = 43;
                    if (ItemDescription != null) { length += ItemDescription.Length; }
                    return length;
                }
            }

            public TransactionInfoBlock() { }
            public TransactionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TransactionType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SourceID.FromBytes(bytes, i); i += 16;
                    IsSourceGroup = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    DestID.FromBytes(bytes, i); i += 16;
                    IsDestGroup = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Amount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ItemDescription = new byte[length];
                    Buffer.BlockCopy(bytes, i, ItemDescription, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(TransactionType, bytes, i); i += 4;
                SourceID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsSourceGroup) ? 1 : 0);
                DestID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsDestGroup) ? 1 : 0);
                Utils.IntToBytes(Amount, bytes, i); i += 4;
                bytes[i++] = (byte)ItemDescription.Length;
                Buffer.BlockCopy(ItemDescription, 0, bytes, i, ItemDescription.Length); i += ItemDescription.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += MoneyData.Length;
                length += TransactionInfo.Length;
                return length;
            }
        }
        public MoneyDataBlock MoneyData;
        public TransactionInfoBlock TransactionInfo;

        public MoneyBalanceReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MoneyBalanceReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 314;
            Header.Reliable = true;
            Header.Zerocoded = true;
            MoneyData = new MoneyDataBlock();
            TransactionInfo = new TransactionInfoBlock();
        }

        public MoneyBalanceReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            MoneyData.FromBytes(bytes, ref i);
            TransactionInfo.FromBytes(bytes, ref i);
        }

        public MoneyBalanceReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            MoneyData.FromBytes(bytes, ref i);
            TransactionInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += MoneyData.Length;
            length += TransactionInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            TransactionInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RoutedMoneyBalanceReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class TargetBlockBlock : PacketBlock
        {
            public uint TargetIP;
            public ushort TargetPort;

            public override int Length
            {
                get
                {
                    return 6;
                }
            }

            public TargetBlockBlock() { }
            public TargetBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetIP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TargetPort = (ushort)((bytes[i++] << 8) + bytes[i++]);
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(TargetIP, bytes, i); i += 4;
                bytes[i++] = (byte)((TargetPort >> 8) % 256);
                bytes[i++] = (byte)(TargetPort % 256);
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID TransactionID;
            public bool TransactionSuccess;
            public int MoneyBalance;
            public int SquareMetersCredit;
            public int SquareMetersCommitted;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 46;
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    TransactionSuccess = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MoneyBalance = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SquareMetersCredit = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SquareMetersCommitted = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((TransactionSuccess) ? 1 : 0);
                Utils.IntToBytes(MoneyBalance, bytes, i); i += 4;
                Utils.IntToBytes(SquareMetersCredit, bytes, i); i += 4;
                Utils.IntToBytes(SquareMetersCommitted, bytes, i); i += 4;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        /// <exclude/>
        public sealed class TransactionInfoBlock : PacketBlock
        {
            public int TransactionType;
            public UUID SourceID;
            public bool IsSourceGroup;
            public UUID DestID;
            public bool IsDestGroup;
            public int Amount;
            public byte[] ItemDescription;

            public override int Length
            {
                get
                {
                    int length = 43;
                    if (ItemDescription != null) { length += ItemDescription.Length; }
                    return length;
                }
            }

            public TransactionInfoBlock() { }
            public TransactionInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TransactionType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SourceID.FromBytes(bytes, i); i += 16;
                    IsSourceGroup = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    DestID.FromBytes(bytes, i); i += 16;
                    IsDestGroup = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Amount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ItemDescription = new byte[length];
                    Buffer.BlockCopy(bytes, i, ItemDescription, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(TransactionType, bytes, i); i += 4;
                SourceID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsSourceGroup) ? 1 : 0);
                DestID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsDestGroup) ? 1 : 0);
                Utils.IntToBytes(Amount, bytes, i); i += 4;
                bytes[i++] = (byte)ItemDescription.Length;
                Buffer.BlockCopy(ItemDescription, 0, bytes, i, ItemDescription.Length); i += ItemDescription.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += TargetBlock.Length;
                length += MoneyData.Length;
                length += TransactionInfo.Length;
                return length;
            }
        }
        public TargetBlockBlock TargetBlock;
        public MoneyDataBlock MoneyData;
        public TransactionInfoBlock TransactionInfo;

        public RoutedMoneyBalanceReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RoutedMoneyBalanceReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 315;
            Header.Reliable = true;
            Header.Zerocoded = true;
            TargetBlock = new TargetBlockBlock();
            MoneyData = new MoneyDataBlock();
            TransactionInfo = new TransactionInfoBlock();
        }

        public RoutedMoneyBalanceReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TargetBlock.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
            TransactionInfo.FromBytes(bytes, ref i);
        }

        public RoutedMoneyBalanceReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TargetBlock.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
            TransactionInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += TargetBlock.Length;
            length += MoneyData.Length;
            length += TransactionInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TargetBlock.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            TransactionInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ActivateGesturesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID AssetID;
            public uint GestureFlags;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    AssetID.FromBytes(bytes, i); i += 16;
                    GestureFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                AssetID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(GestureFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;

        public ActivateGesturesPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ActivateGestures;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 316;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
        }

        public ActivateGesturesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public ActivateGesturesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DeactivateGesturesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID ItemID;
            public uint GestureFlags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    GestureFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(GestureFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;

        public DeactivateGesturesPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.DeactivateGestures;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 317;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
        }

        public DeactivateGesturesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public DeactivateGesturesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class MuteListUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class MuteDataBlock : PacketBlock
        {
            public UUID AgentID;
            public byte[] Filename;

            public override int Length
            {
                get
                {
                    int length = 17;
                    if (Filename != null) { length += Filename.Length; }
                    return length;
                }
            }

            public MuteDataBlock() { }
            public MuteDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Filename = new byte[length];
                    Buffer.BlockCopy(bytes, i, Filename, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Filename.Length;
                Buffer.BlockCopy(Filename, 0, bytes, i, Filename.Length); i += Filename.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += MuteData.Length;
                return length;
            }
        }
        public MuteDataBlock MuteData;

        public MuteListUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MuteListUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 318;
            Header.Reliable = true;
            MuteData = new MuteDataBlock();
        }

        public MuteListUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            MuteData.FromBytes(bytes, ref i);
        }

        public MuteListUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            MuteData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += MuteData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            MuteData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UseCachedMuteListPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public UseCachedMuteListPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UseCachedMuteList;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 319;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public UseCachedMuteListPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public UseCachedMuteListPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GrantUserRightsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RightsBlock : PacketBlock
        {
            public UUID AgentRelated;
            public int RelatedRights;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public RightsBlock() { }
            public RightsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentRelated.FromBytes(bytes, i); i += 16;
                    RelatedRights = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentRelated.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(RelatedRights, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Rights.Length; j++)
                    length += Rights[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RightsBlock[] Rights;

        public GrantUserRightsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GrantUserRights;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 320;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Rights = null;
        }

        public GrantUserRightsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Rights == null || Rights.Length != -1) {
                Rights = new RightsBlock[count];
                for(int j = 0; j < count; j++)
                { Rights[j] = new RightsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Rights[j].FromBytes(bytes, ref i); }
        }

        public GrantUserRightsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Rights == null || Rights.Length != count) {
                Rights = new RightsBlock[count];
                for(int j = 0; j < count; j++)
                { Rights[j] = new RightsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Rights[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Rights.Length; j++) { length += Rights[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Rights.Length;
            for (int j = 0; j < Rights.Length; j++) { Rights[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RightsStart = 0;
            do
            {
                int variableLength = 0;
                int RightsCount = 0;

                i = RightsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Rights.Length) {
                    int blockLength = Rights[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RightsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RightsCount;
                for (i = RightsStart; i < RightsStart + RightsCount; i++) { Rights[i].ToBytes(packet, ref length); }
                RightsStart += RightsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RightsStart < Rights.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ChangeUserRightsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RightsBlock : PacketBlock
        {
            public UUID AgentRelated;
            public int RelatedRights;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public RightsBlock() { }
            public RightsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentRelated.FromBytes(bytes, i); i += 16;
                    RelatedRights = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentRelated.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(RelatedRights, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < Rights.Length; j++)
                    length += Rights[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RightsBlock[] Rights;

        public ChangeUserRightsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ChangeUserRights;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 321;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Rights = null;
        }

        public ChangeUserRightsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Rights == null || Rights.Length != -1) {
                Rights = new RightsBlock[count];
                for(int j = 0; j < count; j++)
                { Rights[j] = new RightsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Rights[j].FromBytes(bytes, ref i); }
        }

        public ChangeUserRightsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Rights == null || Rights.Length != count) {
                Rights = new RightsBlock[count];
                for(int j = 0; j < count; j++)
                { Rights[j] = new RightsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Rights[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Rights.Length; j++) { length += Rights[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Rights.Length;
            for (int j = 0; j < Rights.Length; j++) { Rights[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RightsStart = 0;
            do
            {
                int variableLength = 0;
                int RightsCount = 0;

                i = RightsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Rights.Length) {
                    int blockLength = Rights[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RightsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RightsCount;
                for (i = RightsStart; i < RightsStart + RightsCount; i++) { Rights[i].ToBytes(packet, ref length); }
                RightsStart += RightsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RightsStart < Rights.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class OnlineNotificationPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentBlockBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentBlockBlock() { }
            public AgentBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < AgentBlock.Length; j++)
                    length += AgentBlock[j].Length;
                return length;
            }
        }
        public AgentBlockBlock[] AgentBlock;

        public OnlineNotificationPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.OnlineNotification;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 322;
            Header.Reliable = true;
            AgentBlock = null;
        }

        public OnlineNotificationPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(AgentBlock == null || AgentBlock.Length != -1) {
                AgentBlock = new AgentBlockBlock[count];
                for(int j = 0; j < count; j++)
                { AgentBlock[j] = new AgentBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentBlock[j].FromBytes(bytes, ref i); }
        }

        public OnlineNotificationPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(AgentBlock == null || AgentBlock.Length != count) {
                AgentBlock = new AgentBlockBlock[count];
                for(int j = 0; j < count; j++)
                { AgentBlock[j] = new AgentBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < AgentBlock.Length; j++) { length += AgentBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AgentBlock.Length;
            for (int j = 0; j < AgentBlock.Length; j++) { AgentBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int AgentBlockStart = 0;
            do
            {
                int variableLength = 0;
                int AgentBlockCount = 0;

                i = AgentBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AgentBlock.Length) {
                    int blockLength = AgentBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AgentBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AgentBlockCount;
                for (i = AgentBlockStart; i < AgentBlockStart + AgentBlockCount; i++) { AgentBlock[i].ToBytes(packet, ref length); }
                AgentBlockStart += AgentBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AgentBlockStart < AgentBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class OfflineNotificationPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentBlockBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentBlockBlock() { }
            public AgentBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < AgentBlock.Length; j++)
                    length += AgentBlock[j].Length;
                return length;
            }
        }
        public AgentBlockBlock[] AgentBlock;

        public OfflineNotificationPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.OfflineNotification;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 323;
            Header.Reliable = true;
            AgentBlock = null;
        }

        public OfflineNotificationPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(AgentBlock == null || AgentBlock.Length != -1) {
                AgentBlock = new AgentBlockBlock[count];
                for(int j = 0; j < count; j++)
                { AgentBlock[j] = new AgentBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentBlock[j].FromBytes(bytes, ref i); }
        }

        public OfflineNotificationPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(AgentBlock == null || AgentBlock.Length != count) {
                AgentBlock = new AgentBlockBlock[count];
                for(int j = 0; j < count; j++)
                { AgentBlock[j] = new AgentBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < AgentBlock.Length; j++) { length += AgentBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AgentBlock.Length;
            for (int j = 0; j < AgentBlock.Length; j++) { AgentBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int AgentBlockStart = 0;
            do
            {
                int variableLength = 0;
                int AgentBlockCount = 0;

                i = AgentBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AgentBlock.Length) {
                    int blockLength = AgentBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AgentBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AgentBlockCount;
                for (i = AgentBlockStart; i < AgentBlockStart + AgentBlockCount; i++) { AgentBlock[i].ToBytes(packet, ref length); }
                AgentBlockStart += AgentBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AgentBlockStart < AgentBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class SetStartLocationRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class StartLocationDataBlock : PacketBlock
        {
            public byte[] SimName;
            public uint LocationID;
            public Vector3 LocationPos;
            public Vector3 LocationLookAt;

            public override int Length
            {
                get
                {
                    int length = 29;
                    if (SimName != null) { length += SimName.Length; }
                    return length;
                }
            }

            public StartLocationDataBlock() { }
            public StartLocationDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    SimName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimName, 0, length); i += length;
                    LocationID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LocationPos.FromBytes(bytes, i); i += 12;
                    LocationLookAt.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)SimName.Length;
                Buffer.BlockCopy(SimName, 0, bytes, i, SimName.Length); i += SimName.Length;
                Utils.UIntToBytes(LocationID, bytes, i); i += 4;
                LocationPos.ToBytes(bytes, i); i += 12;
                LocationLookAt.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += StartLocationData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public StartLocationDataBlock StartLocationData;

        public SetStartLocationRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SetStartLocationRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 324;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            StartLocationData = new StartLocationDataBlock();
        }

        public SetStartLocationRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            StartLocationData.FromBytes(bytes, ref i);
        }

        public SetStartLocationRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            StartLocationData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += StartLocationData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            StartLocationData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AssetUploadRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AssetBlockBlock : PacketBlock
        {
            public UUID TransactionID;
            public sbyte Type;
            public bool Tempfile;
            public bool StoreLocal;
            public byte[] AssetData;

            public override int Length
            {
                get
                {
                    int length = 21;
                    if (AssetData != null) { length += AssetData.Length; }
                    return length;
                }
            }

            public AssetBlockBlock() { }
            public AssetBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    Tempfile = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    StoreLocal = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    AssetData = new byte[length];
                    Buffer.BlockCopy(bytes, i, AssetData, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)((Tempfile) ? 1 : 0);
                bytes[i++] = (byte)((StoreLocal) ? 1 : 0);
                bytes[i++] = (byte)(AssetData.Length % 256);
                bytes[i++] = (byte)((AssetData.Length >> 8) % 256);
                Buffer.BlockCopy(AssetData, 0, bytes, i, AssetData.Length); i += AssetData.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AssetBlock.Length;
                return length;
            }
        }
        public AssetBlockBlock AssetBlock;

        public AssetUploadRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AssetUploadRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 333;
            Header.Reliable = true;
            AssetBlock = new AssetBlockBlock();
        }

        public AssetUploadRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AssetBlock.FromBytes(bytes, ref i);
        }

        public AssetUploadRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AssetBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AssetBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AssetBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AssetUploadCompletePacket : Packet
    {
        /// <exclude/>
        public sealed class AssetBlockBlock : PacketBlock
        {
            public UUID UUID;
            public sbyte Type;
            public bool Success;

            public override int Length
            {
                get
                {
                    return 18;
                }
            }

            public AssetBlockBlock() { }
            public AssetBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    UUID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    Success = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                UUID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)((Success) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AssetBlock.Length;
                return length;
            }
        }
        public AssetBlockBlock AssetBlock;

        public AssetUploadCompletePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AssetUploadComplete;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 334;
            Header.Reliable = true;
            AssetBlock = new AssetBlockBlock();
        }

        public AssetUploadCompletePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AssetBlock.FromBytes(bytes, ref i);
        }

        public AssetUploadCompletePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AssetBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AssetBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AssetBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CreateGroupRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public byte[] Name;
            public byte[] Charter;
            public bool ShowInList;
            public UUID InsigniaID;
            public int MembershipFee;
            public bool OpenEnrollment;
            public bool AllowPublish;
            public bool MaturePublish;

            public override int Length
            {
                get
                {
                    int length = 27;
                    if (Name != null) { length += Name.Length; }
                    if (Charter != null) { length += Charter.Length; }
                    return length;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Charter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Charter, 0, length); i += length;
                    ShowInList = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    InsigniaID.FromBytes(bytes, i); i += 16;
                    MembershipFee = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OpenEnrollment = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AllowPublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MaturePublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)(Charter.Length % 256);
                bytes[i++] = (byte)((Charter.Length >> 8) % 256);
                Buffer.BlockCopy(Charter, 0, bytes, i, Charter.Length); i += Charter.Length;
                bytes[i++] = (byte)((ShowInList) ? 1 : 0);
                InsigniaID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(MembershipFee, bytes, i); i += 4;
                bytes[i++] = (byte)((OpenEnrollment) ? 1 : 0);
                bytes[i++] = (byte)((AllowPublish) ? 1 : 0);
                bytes[i++] = (byte)((MaturePublish) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public CreateGroupRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CreateGroupRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 339;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public CreateGroupRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public CreateGroupRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CreateGroupReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ReplyDataBlock : PacketBlock
        {
            public UUID GroupID;
            public bool Success;
            public byte[] Message;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (Message != null) { length += Message.Length; }
                    return length;
                }
            }

            public ReplyDataBlock() { }
            public ReplyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    Success = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Success) ? 1 : 0);
                bytes[i++] = (byte)Message.Length;
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ReplyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ReplyDataBlock ReplyData;

        public CreateGroupReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CreateGroupReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 340;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ReplyData = new ReplyDataBlock();
        }

        public CreateGroupReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ReplyData.FromBytes(bytes, ref i);
        }

        public CreateGroupReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ReplyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ReplyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ReplyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UpdateGroupInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public byte[] Charter;
            public bool ShowInList;
            public UUID InsigniaID;
            public int MembershipFee;
            public bool OpenEnrollment;
            public bool AllowPublish;
            public bool MaturePublish;

            public override int Length
            {
                get
                {
                    int length = 42;
                    if (Charter != null) { length += Charter.Length; }
                    return length;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Charter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Charter, 0, length); i += length;
                    ShowInList = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    InsigniaID.FromBytes(bytes, i); i += 16;
                    MembershipFee = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OpenEnrollment = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AllowPublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MaturePublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(Charter.Length % 256);
                bytes[i++] = (byte)((Charter.Length >> 8) % 256);
                Buffer.BlockCopy(Charter, 0, bytes, i, Charter.Length); i += Charter.Length;
                bytes[i++] = (byte)((ShowInList) ? 1 : 0);
                InsigniaID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(MembershipFee, bytes, i); i += 4;
                bytes[i++] = (byte)((OpenEnrollment) ? 1 : 0);
                bytes[i++] = (byte)((AllowPublish) ? 1 : 0);
                bytes[i++] = (byte)((MaturePublish) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public UpdateGroupInfoPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UpdateGroupInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 341;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public UpdateGroupInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public UpdateGroupInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupRoleChangesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RoleChangeBlock : PacketBlock
        {
            public UUID RoleID;
            public UUID MemberID;
            public uint Change;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public RoleChangeBlock() { }
            public RoleChangeBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RoleID.FromBytes(bytes, i); i += 16;
                    MemberID.FromBytes(bytes, i); i += 16;
                    Change = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RoleID.ToBytes(bytes, i); i += 16;
                MemberID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Change, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < RoleChange.Length; j++)
                    length += RoleChange[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RoleChangeBlock[] RoleChange;

        public GroupRoleChangesPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupRoleChanges;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 342;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RoleChange = null;
        }

        public GroupRoleChangesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RoleChange == null || RoleChange.Length != -1) {
                RoleChange = new RoleChangeBlock[count];
                for(int j = 0; j < count; j++)
                { RoleChange[j] = new RoleChangeBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RoleChange[j].FromBytes(bytes, ref i); }
        }

        public GroupRoleChangesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RoleChange == null || RoleChange.Length != count) {
                RoleChange = new RoleChangeBlock[count];
                for(int j = 0; j < count; j++)
                { RoleChange[j] = new RoleChangeBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RoleChange[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < RoleChange.Length; j++) { length += RoleChange[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RoleChange.Length;
            for (int j = 0; j < RoleChange.Length; j++) { RoleChange[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RoleChangeStart = 0;
            do
            {
                int variableLength = 0;
                int RoleChangeCount = 0;

                i = RoleChangeStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RoleChange.Length) {
                    int blockLength = RoleChange[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RoleChangeCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RoleChangeCount;
                for (i = RoleChangeStart; i < RoleChangeStart + RoleChangeCount; i++) { RoleChange[i].ToBytes(packet, ref length); }
                RoleChangeStart += RoleChangeCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RoleChangeStart < RoleChange.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class JoinGroupRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public JoinGroupRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.JoinGroupRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 343;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public JoinGroupRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public JoinGroupRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class JoinGroupReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public bool Success;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    Success = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Success) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public JoinGroupReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.JoinGroupReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 344;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public JoinGroupReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public JoinGroupReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class EjectGroupMemberRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EjectDataBlock : PacketBlock
        {
            public UUID EjecteeID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public EjectDataBlock() { }
            public EjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    EjecteeID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                EjecteeID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += GroupData.Length;
                for (int j = 0; j < EjectData.Length; j++)
                    length += EjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public EjectDataBlock[] EjectData;

        public EjectGroupMemberRequestPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.EjectGroupMemberRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 345;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            EjectData = null;
        }

        public EjectGroupMemberRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(EjectData == null || EjectData.Length != -1) {
                EjectData = new EjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { EjectData[j] = new EjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { EjectData[j].FromBytes(bytes, ref i); }
        }

        public EjectGroupMemberRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(EjectData == null || EjectData.Length != count) {
                EjectData = new EjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { EjectData[j] = new EjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { EjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length++;
            for (int j = 0; j < EjectData.Length; j++) { length += EjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)EjectData.Length;
            for (int j = 0; j < EjectData.Length; j++) { EjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += GroupData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            GroupData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int EjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int EjectDataCount = 0;

                i = EjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < EjectData.Length) {
                    int blockLength = EjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++EjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)EjectDataCount;
                for (i = EjectDataStart; i < EjectDataStart + EjectDataCount; i++) { EjectData[i].ToBytes(packet, ref length); }
                EjectDataStart += EjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                EjectDataStart < EjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class EjectGroupMemberReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EjectDataBlock : PacketBlock
        {
            public bool Success;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public EjectDataBlock() { }
            public EjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Success = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((Success) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                length += EjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public EjectDataBlock EjectData;

        public EjectGroupMemberReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.EjectGroupMemberReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 346;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            EjectData = new EjectDataBlock();
        }

        public EjectGroupMemberReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            EjectData.FromBytes(bytes, ref i);
        }

        public EjectGroupMemberReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            EjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length += EjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            EjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LeaveGroupRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public LeaveGroupRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LeaveGroupRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 347;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public LeaveGroupRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public LeaveGroupRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LeaveGroupReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public bool Success;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    Success = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Success) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public LeaveGroupReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LeaveGroupReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 348;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public LeaveGroupReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public LeaveGroupReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class InviteGroupRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InviteDataBlock : PacketBlock
        {
            public UUID InviteeID;
            public UUID RoleID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public InviteDataBlock() { }
            public InviteDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    InviteeID.FromBytes(bytes, i); i += 16;
                    RoleID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                InviteeID.ToBytes(bytes, i); i += 16;
                RoleID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += GroupData.Length;
                for (int j = 0; j < InviteData.Length; j++)
                    length += InviteData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public InviteDataBlock[] InviteData;

        public InviteGroupRequestPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.InviteGroupRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 349;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            InviteData = null;
        }

        public InviteGroupRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InviteData == null || InviteData.Length != -1) {
                InviteData = new InviteDataBlock[count];
                for(int j = 0; j < count; j++)
                { InviteData[j] = new InviteDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InviteData[j].FromBytes(bytes, ref i); }
        }

        public InviteGroupRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(InviteData == null || InviteData.Length != count) {
                InviteData = new InviteDataBlock[count];
                for(int j = 0; j < count; j++)
                { InviteData[j] = new InviteDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { InviteData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length++;
            for (int j = 0; j < InviteData.Length; j++) { length += InviteData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)InviteData.Length;
            for (int j = 0; j < InviteData.Length; j++) { InviteData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += GroupData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            GroupData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int InviteDataStart = 0;
            do
            {
                int variableLength = 0;
                int InviteDataCount = 0;

                i = InviteDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < InviteData.Length) {
                    int blockLength = InviteData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++InviteDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)InviteDataCount;
                for (i = InviteDataStart; i < InviteDataStart + InviteDataCount; i++) { InviteData[i].ToBytes(packet, ref length); }
                InviteDataStart += InviteDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                InviteDataStart < InviteData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupProfileRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public GroupProfileRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupProfileRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 351;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public GroupProfileRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public GroupProfileRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupProfileReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public byte[] Name;
            public byte[] Charter;
            public bool ShowInList;
            public byte[] MemberTitle;
            public ulong PowersMask;
            public UUID InsigniaID;
            public UUID FounderID;
            public int MembershipFee;
            public bool OpenEnrollment;
            public int Money;
            public int GroupMembershipCount;
            public int GroupRolesCount;
            public bool AllowPublish;
            public bool MaturePublish;
            public UUID OwnerRole;

            public override int Length
            {
                get
                {
                    int length = 96;
                    if (Name != null) { length += Name.Length; }
                    if (Charter != null) { length += Charter.Length; }
                    if (MemberTitle != null) { length += MemberTitle.Length; }
                    return length;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Charter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Charter, 0, length); i += length;
                    ShowInList = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    MemberTitle = new byte[length];
                    Buffer.BlockCopy(bytes, i, MemberTitle, 0, length); i += length;
                    PowersMask = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    InsigniaID.FromBytes(bytes, i); i += 16;
                    FounderID.FromBytes(bytes, i); i += 16;
                    MembershipFee = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OpenEnrollment = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Money = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMembershipCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupRolesCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AllowPublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MaturePublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    OwnerRole.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)(Charter.Length % 256);
                bytes[i++] = (byte)((Charter.Length >> 8) % 256);
                Buffer.BlockCopy(Charter, 0, bytes, i, Charter.Length); i += Charter.Length;
                bytes[i++] = (byte)((ShowInList) ? 1 : 0);
                bytes[i++] = (byte)MemberTitle.Length;
                Buffer.BlockCopy(MemberTitle, 0, bytes, i, MemberTitle.Length); i += MemberTitle.Length;
                Utils.UInt64ToBytes(PowersMask, bytes, i); i += 8;
                InsigniaID.ToBytes(bytes, i); i += 16;
                FounderID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(MembershipFee, bytes, i); i += 4;
                bytes[i++] = (byte)((OpenEnrollment) ? 1 : 0);
                Utils.IntToBytes(Money, bytes, i); i += 4;
                Utils.IntToBytes(GroupMembershipCount, bytes, i); i += 4;
                Utils.IntToBytes(GroupRolesCount, bytes, i); i += 4;
                bytes[i++] = (byte)((AllowPublish) ? 1 : 0);
                bytes[i++] = (byte)((MaturePublish) ? 1 : 0);
                OwnerRole.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public GroupProfileReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupProfileReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 352;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public GroupProfileReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public GroupProfileReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupAccountSummaryRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public int IntervalDays;
            public int CurrentInterval;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    IntervalDays = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CurrentInterval = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(IntervalDays, bytes, i); i += 4;
                Utils.IntToBytes(CurrentInterval, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MoneyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;

        public GroupAccountSummaryRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupAccountSummaryRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 353;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
        }

        public GroupAccountSummaryRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public GroupAccountSummaryRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupAccountSummaryReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public int IntervalDays;
            public int CurrentInterval;
            public byte[] StartDate;
            public int Balance;
            public int TotalCredits;
            public int TotalDebits;
            public int ObjectTaxCurrent;
            public int LightTaxCurrent;
            public int LandTaxCurrent;
            public int GroupTaxCurrent;
            public int ParcelDirFeeCurrent;
            public int ObjectTaxEstimate;
            public int LightTaxEstimate;
            public int LandTaxEstimate;
            public int GroupTaxEstimate;
            public int ParcelDirFeeEstimate;
            public int NonExemptMembers;
            public byte[] LastTaxDate;
            public byte[] TaxDate;

            public override int Length
            {
                get
                {
                    int length = 83;
                    if (StartDate != null) { length += StartDate.Length; }
                    if (LastTaxDate != null) { length += LastTaxDate.Length; }
                    if (TaxDate != null) { length += TaxDate.Length; }
                    return length;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    IntervalDays = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CurrentInterval = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    StartDate = new byte[length];
                    Buffer.BlockCopy(bytes, i, StartDate, 0, length); i += length;
                    Balance = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TotalCredits = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TotalDebits = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ObjectTaxCurrent = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LightTaxCurrent = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LandTaxCurrent = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupTaxCurrent = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelDirFeeCurrent = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ObjectTaxEstimate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LightTaxEstimate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LandTaxEstimate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupTaxEstimate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelDirFeeEstimate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NonExemptMembers = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    LastTaxDate = new byte[length];
                    Buffer.BlockCopy(bytes, i, LastTaxDate, 0, length); i += length;
                    length = bytes[i++];
                    TaxDate = new byte[length];
                    Buffer.BlockCopy(bytes, i, TaxDate, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(IntervalDays, bytes, i); i += 4;
                Utils.IntToBytes(CurrentInterval, bytes, i); i += 4;
                bytes[i++] = (byte)StartDate.Length;
                Buffer.BlockCopy(StartDate, 0, bytes, i, StartDate.Length); i += StartDate.Length;
                Utils.IntToBytes(Balance, bytes, i); i += 4;
                Utils.IntToBytes(TotalCredits, bytes, i); i += 4;
                Utils.IntToBytes(TotalDebits, bytes, i); i += 4;
                Utils.IntToBytes(ObjectTaxCurrent, bytes, i); i += 4;
                Utils.IntToBytes(LightTaxCurrent, bytes, i); i += 4;
                Utils.IntToBytes(LandTaxCurrent, bytes, i); i += 4;
                Utils.IntToBytes(GroupTaxCurrent, bytes, i); i += 4;
                Utils.IntToBytes(ParcelDirFeeCurrent, bytes, i); i += 4;
                Utils.IntToBytes(ObjectTaxEstimate, bytes, i); i += 4;
                Utils.IntToBytes(LightTaxEstimate, bytes, i); i += 4;
                Utils.IntToBytes(LandTaxEstimate, bytes, i); i += 4;
                Utils.IntToBytes(GroupTaxEstimate, bytes, i); i += 4;
                Utils.IntToBytes(ParcelDirFeeEstimate, bytes, i); i += 4;
                Utils.IntToBytes(NonExemptMembers, bytes, i); i += 4;
                bytes[i++] = (byte)LastTaxDate.Length;
                Buffer.BlockCopy(LastTaxDate, 0, bytes, i, LastTaxDate.Length); i += LastTaxDate.Length;
                bytes[i++] = (byte)TaxDate.Length;
                Buffer.BlockCopy(TaxDate, 0, bytes, i, TaxDate.Length); i += TaxDate.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MoneyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;

        public GroupAccountSummaryReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupAccountSummaryReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 354;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
        }

        public GroupAccountSummaryReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public GroupAccountSummaryReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupAccountDetailsRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public int IntervalDays;
            public int CurrentInterval;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    IntervalDays = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CurrentInterval = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(IntervalDays, bytes, i); i += 4;
                Utils.IntToBytes(CurrentInterval, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MoneyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;

        public GroupAccountDetailsRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupAccountDetailsRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 355;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
        }

        public GroupAccountDetailsRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public GroupAccountDetailsRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupAccountDetailsReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public int IntervalDays;
            public int CurrentInterval;
            public byte[] StartDate;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (StartDate != null) { length += StartDate.Length; }
                    return length;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    IntervalDays = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CurrentInterval = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    StartDate = new byte[length];
                    Buffer.BlockCopy(bytes, i, StartDate, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(IntervalDays, bytes, i); i += 4;
                Utils.IntToBytes(CurrentInterval, bytes, i); i += 4;
                bytes[i++] = (byte)StartDate.Length;
                Buffer.BlockCopy(StartDate, 0, bytes, i, StartDate.Length); i += StartDate.Length;
            }

        }

        /// <exclude/>
        public sealed class HistoryDataBlock : PacketBlock
        {
            public byte[] Description;
            public int Amount;

            public override int Length
            {
                get
                {
                    int length = 5;
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public HistoryDataBlock() { }
            public HistoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    Amount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(Amount, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += MoneyData.Length;
                for (int j = 0; j < HistoryData.Length; j++)
                    length += HistoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;
        public HistoryDataBlock[] HistoryData;

        public GroupAccountDetailsReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupAccountDetailsReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 356;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
            HistoryData = null;
        }

        public GroupAccountDetailsReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(HistoryData == null || HistoryData.Length != -1) {
                HistoryData = new HistoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { HistoryData[j] = new HistoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { HistoryData[j].FromBytes(bytes, ref i); }
        }

        public GroupAccountDetailsReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(HistoryData == null || HistoryData.Length != count) {
                HistoryData = new HistoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { HistoryData[j] = new HistoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { HistoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            length++;
            for (int j = 0; j < HistoryData.Length; j++) { length += HistoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)HistoryData.Length;
            for (int j = 0; j < HistoryData.Length; j++) { HistoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += MoneyData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            MoneyData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int HistoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int HistoryDataCount = 0;

                i = HistoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < HistoryData.Length) {
                    int blockLength = HistoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++HistoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)HistoryDataCount;
                for (i = HistoryDataStart; i < HistoryDataStart + HistoryDataCount; i++) { HistoryData[i].ToBytes(packet, ref length); }
                HistoryDataStart += HistoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                HistoryDataStart < HistoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupAccountTransactionsRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public int IntervalDays;
            public int CurrentInterval;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    IntervalDays = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CurrentInterval = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(IntervalDays, bytes, i); i += 4;
                Utils.IntToBytes(CurrentInterval, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += MoneyData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;

        public GroupAccountTransactionsRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupAccountTransactionsRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 357;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
        }

        public GroupAccountTransactionsRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public GroupAccountTransactionsRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupAccountTransactionsReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class MoneyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public int IntervalDays;
            public int CurrentInterval;
            public byte[] StartDate;

            public override int Length
            {
                get
                {
                    int length = 25;
                    if (StartDate != null) { length += StartDate.Length; }
                    return length;
                }
            }

            public MoneyDataBlock() { }
            public MoneyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    IntervalDays = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CurrentInterval = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    StartDate = new byte[length];
                    Buffer.BlockCopy(bytes, i, StartDate, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(IntervalDays, bytes, i); i += 4;
                Utils.IntToBytes(CurrentInterval, bytes, i); i += 4;
                bytes[i++] = (byte)StartDate.Length;
                Buffer.BlockCopy(StartDate, 0, bytes, i, StartDate.Length); i += StartDate.Length;
            }

        }

        /// <exclude/>
        public sealed class HistoryDataBlock : PacketBlock
        {
            public byte[] Time;
            public byte[] User;
            public int Type;
            public byte[] Item;
            public int Amount;

            public override int Length
            {
                get
                {
                    int length = 11;
                    if (Time != null) { length += Time.Length; }
                    if (User != null) { length += User.Length; }
                    if (Item != null) { length += Item.Length; }
                    return length;
                }
            }

            public HistoryDataBlock() { }
            public HistoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Time = new byte[length];
                    Buffer.BlockCopy(bytes, i, Time, 0, length); i += length;
                    length = bytes[i++];
                    User = new byte[length];
                    Buffer.BlockCopy(bytes, i, User, 0, length); i += length;
                    Type = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Item = new byte[length];
                    Buffer.BlockCopy(bytes, i, Item, 0, length); i += length;
                    Amount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Time.Length;
                Buffer.BlockCopy(Time, 0, bytes, i, Time.Length); i += Time.Length;
                bytes[i++] = (byte)User.Length;
                Buffer.BlockCopy(User, 0, bytes, i, User.Length); i += User.Length;
                Utils.IntToBytes(Type, bytes, i); i += 4;
                bytes[i++] = (byte)Item.Length;
                Buffer.BlockCopy(Item, 0, bytes, i, Item.Length); i += Item.Length;
                Utils.IntToBytes(Amount, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += MoneyData.Length;
                for (int j = 0; j < HistoryData.Length; j++)
                    length += HistoryData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MoneyDataBlock MoneyData;
        public HistoryDataBlock[] HistoryData;

        public GroupAccountTransactionsReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupAccountTransactionsReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 358;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            MoneyData = new MoneyDataBlock();
            HistoryData = null;
        }

        public GroupAccountTransactionsReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(HistoryData == null || HistoryData.Length != -1) {
                HistoryData = new HistoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { HistoryData[j] = new HistoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { HistoryData[j].FromBytes(bytes, ref i); }
        }

        public GroupAccountTransactionsReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            MoneyData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(HistoryData == null || HistoryData.Length != count) {
                HistoryData = new HistoryDataBlock[count];
                for(int j = 0; j < count; j++)
                { HistoryData[j] = new HistoryDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { HistoryData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += MoneyData.Length;
            length++;
            for (int j = 0; j < HistoryData.Length; j++) { length += HistoryData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            MoneyData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)HistoryData.Length;
            for (int j = 0; j < HistoryData.Length; j++) { HistoryData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += MoneyData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            MoneyData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int HistoryDataStart = 0;
            do
            {
                int variableLength = 0;
                int HistoryDataCount = 0;

                i = HistoryDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < HistoryData.Length) {
                    int blockLength = HistoryData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++HistoryDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)HistoryDataCount;
                for (i = HistoryDataStart; i < HistoryDataStart + HistoryDataCount; i++) { HistoryData[i].ToBytes(packet, ref length); }
                HistoryDataStart += HistoryDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                HistoryDataStart < HistoryData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupActiveProposalsRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                length += TransactionData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public TransactionDataBlock TransactionData;

        public GroupActiveProposalsRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupActiveProposalsRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 359;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            TransactionData = new TransactionDataBlock();
        }

        public GroupActiveProposalsRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
        }

        public GroupActiveProposalsRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length += TransactionData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupActiveProposalItemReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;
            public uint TotalNumItems;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                    TotalNumItems = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(TotalNumItems, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ProposalDataBlock : PacketBlock
        {
            public UUID VoteID;
            public UUID VoteInitiator;
            public byte[] TerseDateID;
            public byte[] StartDateTime;
            public byte[] EndDateTime;
            public bool AlreadyVoted;
            public byte[] VoteCast;
            public float Majority;
            public int Quorum;
            public byte[] ProposalText;

            public override int Length
            {
                get
                {
                    int length = 46;
                    if (TerseDateID != null) { length += TerseDateID.Length; }
                    if (StartDateTime != null) { length += StartDateTime.Length; }
                    if (EndDateTime != null) { length += EndDateTime.Length; }
                    if (VoteCast != null) { length += VoteCast.Length; }
                    if (ProposalText != null) { length += ProposalText.Length; }
                    return length;
                }
            }

            public ProposalDataBlock() { }
            public ProposalDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    VoteID.FromBytes(bytes, i); i += 16;
                    VoteInitiator.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    TerseDateID = new byte[length];
                    Buffer.BlockCopy(bytes, i, TerseDateID, 0, length); i += length;
                    length = bytes[i++];
                    StartDateTime = new byte[length];
                    Buffer.BlockCopy(bytes, i, StartDateTime, 0, length); i += length;
                    length = bytes[i++];
                    EndDateTime = new byte[length];
                    Buffer.BlockCopy(bytes, i, EndDateTime, 0, length); i += length;
                    AlreadyVoted = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    VoteCast = new byte[length];
                    Buffer.BlockCopy(bytes, i, VoteCast, 0, length); i += length;
                    Majority = Utils.BytesToFloat(bytes, i); i += 4;
                    Quorum = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ProposalText = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProposalText, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                VoteID.ToBytes(bytes, i); i += 16;
                VoteInitiator.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)TerseDateID.Length;
                Buffer.BlockCopy(TerseDateID, 0, bytes, i, TerseDateID.Length); i += TerseDateID.Length;
                bytes[i++] = (byte)StartDateTime.Length;
                Buffer.BlockCopy(StartDateTime, 0, bytes, i, StartDateTime.Length); i += StartDateTime.Length;
                bytes[i++] = (byte)EndDateTime.Length;
                Buffer.BlockCopy(EndDateTime, 0, bytes, i, EndDateTime.Length); i += EndDateTime.Length;
                bytes[i++] = (byte)((AlreadyVoted) ? 1 : 0);
                bytes[i++] = (byte)VoteCast.Length;
                Buffer.BlockCopy(VoteCast, 0, bytes, i, VoteCast.Length); i += VoteCast.Length;
                Utils.FloatToBytes(Majority, bytes, i); i += 4;
                Utils.IntToBytes(Quorum, bytes, i); i += 4;
                bytes[i++] = (byte)ProposalText.Length;
                Buffer.BlockCopy(ProposalText, 0, bytes, i, ProposalText.Length); i += ProposalText.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += TransactionData.Length;
                for (int j = 0; j < ProposalData.Length; j++)
                    length += ProposalData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionDataBlock TransactionData;
        public ProposalDataBlock[] ProposalData;

        public GroupActiveProposalItemReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupActiveProposalItemReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 360;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            TransactionData = new TransactionDataBlock();
            ProposalData = null;
        }

        public GroupActiveProposalItemReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ProposalData == null || ProposalData.Length != -1) {
                ProposalData = new ProposalDataBlock[count];
                for(int j = 0; j < count; j++)
                { ProposalData[j] = new ProposalDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ProposalData[j].FromBytes(bytes, ref i); }
        }

        public GroupActiveProposalItemReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ProposalData == null || ProposalData.Length != count) {
                ProposalData = new ProposalDataBlock[count];
                for(int j = 0; j < count; j++)
                { ProposalData[j] = new ProposalDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ProposalData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionData.Length;
            length++;
            for (int j = 0; j < ProposalData.Length; j++) { length += ProposalData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ProposalData.Length;
            for (int j = 0; j < ProposalData.Length; j++) { ProposalData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += TransactionData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            TransactionData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ProposalDataStart = 0;
            do
            {
                int variableLength = 0;
                int ProposalDataCount = 0;

                i = ProposalDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ProposalData.Length) {
                    int blockLength = ProposalData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ProposalDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ProposalDataCount;
                for (i = ProposalDataStart; i < ProposalDataStart + ProposalDataCount; i++) { ProposalData[i].ToBytes(packet, ref length); }
                ProposalDataStart += ProposalDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ProposalDataStart < ProposalData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupVoteHistoryRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                length += TransactionData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public TransactionDataBlock TransactionData;

        public GroupVoteHistoryRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupVoteHistoryRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 361;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            TransactionData = new TransactionDataBlock();
        }

        public GroupVoteHistoryRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
        }

        public GroupVoteHistoryRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length += TransactionData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupVoteHistoryItemReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TransactionDataBlock : PacketBlock
        {
            public UUID TransactionID;
            public uint TotalNumItems;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public TransactionDataBlock() { }
            public TransactionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TransactionID.FromBytes(bytes, i); i += 16;
                    TotalNumItems = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransactionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(TotalNumItems, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class HistoryItemDataBlock : PacketBlock
        {
            public UUID VoteID;
            public byte[] TerseDateID;
            public byte[] StartDateTime;
            public byte[] EndDateTime;
            public UUID VoteInitiator;
            public byte[] VoteType;
            public byte[] VoteResult;
            public float Majority;
            public int Quorum;
            public byte[] ProposalText;

            public override int Length
            {
                get
                {
                    int length = 47;
                    if (TerseDateID != null) { length += TerseDateID.Length; }
                    if (StartDateTime != null) { length += StartDateTime.Length; }
                    if (EndDateTime != null) { length += EndDateTime.Length; }
                    if (VoteType != null) { length += VoteType.Length; }
                    if (VoteResult != null) { length += VoteResult.Length; }
                    if (ProposalText != null) { length += ProposalText.Length; }
                    return length;
                }
            }

            public HistoryItemDataBlock() { }
            public HistoryItemDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    VoteID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    TerseDateID = new byte[length];
                    Buffer.BlockCopy(bytes, i, TerseDateID, 0, length); i += length;
                    length = bytes[i++];
                    StartDateTime = new byte[length];
                    Buffer.BlockCopy(bytes, i, StartDateTime, 0, length); i += length;
                    length = bytes[i++];
                    EndDateTime = new byte[length];
                    Buffer.BlockCopy(bytes, i, EndDateTime, 0, length); i += length;
                    VoteInitiator.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    VoteType = new byte[length];
                    Buffer.BlockCopy(bytes, i, VoteType, 0, length); i += length;
                    length = bytes[i++];
                    VoteResult = new byte[length];
                    Buffer.BlockCopy(bytes, i, VoteResult, 0, length); i += length;
                    Majority = Utils.BytesToFloat(bytes, i); i += 4;
                    Quorum = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    ProposalText = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProposalText, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                VoteID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)TerseDateID.Length;
                Buffer.BlockCopy(TerseDateID, 0, bytes, i, TerseDateID.Length); i += TerseDateID.Length;
                bytes[i++] = (byte)StartDateTime.Length;
                Buffer.BlockCopy(StartDateTime, 0, bytes, i, StartDateTime.Length); i += StartDateTime.Length;
                bytes[i++] = (byte)EndDateTime.Length;
                Buffer.BlockCopy(EndDateTime, 0, bytes, i, EndDateTime.Length); i += EndDateTime.Length;
                VoteInitiator.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)VoteType.Length;
                Buffer.BlockCopy(VoteType, 0, bytes, i, VoteType.Length); i += VoteType.Length;
                bytes[i++] = (byte)VoteResult.Length;
                Buffer.BlockCopy(VoteResult, 0, bytes, i, VoteResult.Length); i += VoteResult.Length;
                Utils.FloatToBytes(Majority, bytes, i); i += 4;
                Utils.IntToBytes(Quorum, bytes, i); i += 4;
                bytes[i++] = (byte)(ProposalText.Length % 256);
                bytes[i++] = (byte)((ProposalText.Length >> 8) % 256);
                Buffer.BlockCopy(ProposalText, 0, bytes, i, ProposalText.Length); i += ProposalText.Length;
            }

        }

        /// <exclude/>
        public sealed class VoteItemBlock : PacketBlock
        {
            public UUID CandidateID;
            public byte[] VoteCast;
            public int NumVotes;

            public override int Length
            {
                get
                {
                    int length = 21;
                    if (VoteCast != null) { length += VoteCast.Length; }
                    return length;
                }
            }

            public VoteItemBlock() { }
            public VoteItemBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    CandidateID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    VoteCast = new byte[length];
                    Buffer.BlockCopy(bytes, i, VoteCast, 0, length); i += length;
                    NumVotes = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                CandidateID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)VoteCast.Length;
                Buffer.BlockCopy(VoteCast, 0, bytes, i, VoteCast.Length); i += VoteCast.Length;
                Utils.IntToBytes(NumVotes, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += TransactionData.Length;
                length += HistoryItemData.Length;
                for (int j = 0; j < VoteItem.Length; j++)
                    length += VoteItem[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TransactionDataBlock TransactionData;
        public HistoryItemDataBlock HistoryItemData;
        public VoteItemBlock[] VoteItem;

        public GroupVoteHistoryItemReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupVoteHistoryItemReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 362;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            TransactionData = new TransactionDataBlock();
            HistoryItemData = new HistoryItemDataBlock();
            VoteItem = null;
        }

        public GroupVoteHistoryItemReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            HistoryItemData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(VoteItem == null || VoteItem.Length != -1) {
                VoteItem = new VoteItemBlock[count];
                for(int j = 0; j < count; j++)
                { VoteItem[j] = new VoteItemBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VoteItem[j].FromBytes(bytes, ref i); }
        }

        public GroupVoteHistoryItemReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TransactionData.FromBytes(bytes, ref i);
            HistoryItemData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(VoteItem == null || VoteItem.Length != count) {
                VoteItem = new VoteItemBlock[count];
                for(int j = 0; j < count; j++)
                { VoteItem[j] = new VoteItemBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VoteItem[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += TransactionData.Length;
            length += HistoryItemData.Length;
            length++;
            for (int j = 0; j < VoteItem.Length; j++) { length += VoteItem[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TransactionData.ToBytes(bytes, ref i);
            HistoryItemData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)VoteItem.Length;
            for (int j = 0; j < VoteItem.Length; j++) { VoteItem[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += TransactionData.Length;
            fixedLength += HistoryItemData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            TransactionData.ToBytes(fixedBytes, ref i);
            HistoryItemData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int VoteItemStart = 0;
            do
            {
                int variableLength = 0;
                int VoteItemCount = 0;

                i = VoteItemStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < VoteItem.Length) {
                    int blockLength = VoteItem[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++VoteItemCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)VoteItemCount;
                for (i = VoteItemStart; i < VoteItemStart + VoteItemCount; i++) { VoteItem[i].ToBytes(packet, ref length); }
                VoteItemStart += VoteItemCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                VoteItemStart < VoteItem.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class StartGroupProposalPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ProposalDataBlock : PacketBlock
        {
            public UUID GroupID;
            public int Quorum;
            public float Majority;
            public int Duration;
            public byte[] ProposalText;

            public override int Length
            {
                get
                {
                    int length = 29;
                    if (ProposalText != null) { length += ProposalText.Length; }
                    return length;
                }
            }

            public ProposalDataBlock() { }
            public ProposalDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    Quorum = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Majority = Utils.BytesToFloat(bytes, i); i += 4;
                    Duration = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    ProposalText = new byte[length];
                    Buffer.BlockCopy(bytes, i, ProposalText, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Quorum, bytes, i); i += 4;
                Utils.FloatToBytes(Majority, bytes, i); i += 4;
                Utils.IntToBytes(Duration, bytes, i); i += 4;
                bytes[i++] = (byte)ProposalText.Length;
                Buffer.BlockCopy(ProposalText, 0, bytes, i, ProposalText.Length); i += ProposalText.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ProposalData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ProposalDataBlock ProposalData;

        public StartGroupProposalPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.StartGroupProposal;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 363;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ProposalData = new ProposalDataBlock();
        }

        public StartGroupProposalPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ProposalData.FromBytes(bytes, ref i);
        }

        public StartGroupProposalPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ProposalData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ProposalData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ProposalData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupProposalBallotPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ProposalDataBlock : PacketBlock
        {
            public UUID ProposalID;
            public UUID GroupID;
            public byte[] VoteCast;

            public override int Length
            {
                get
                {
                    int length = 33;
                    if (VoteCast != null) { length += VoteCast.Length; }
                    return length;
                }
            }

            public ProposalDataBlock() { }
            public ProposalDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ProposalID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    VoteCast = new byte[length];
                    Buffer.BlockCopy(bytes, i, VoteCast, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ProposalID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)VoteCast.Length;
                Buffer.BlockCopy(VoteCast, 0, bytes, i, VoteCast.Length); i += VoteCast.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ProposalData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ProposalDataBlock ProposalData;

        public GroupProposalBallotPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupProposalBallot;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 364;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ProposalData = new ProposalDataBlock();
        }

        public GroupProposalBallotPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ProposalData.FromBytes(bytes, ref i);
        }

        public GroupProposalBallotPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ProposalData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ProposalData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ProposalData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupMembersRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public UUID RequestID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public GroupMembersRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupMembersRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 366;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public GroupMembersRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public GroupMembersRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupMembersReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public UUID RequestID;
            public int MemberCount;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                    MemberCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(MemberCount, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class MemberDataBlock : PacketBlock
        {
            public UUID AgentID;
            public int Contribution;
            public byte[] OnlineStatus;
            public ulong AgentPowers;
            public byte[] Title;
            public bool IsOwner;

            public override int Length
            {
                get
                {
                    int length = 31;
                    if (OnlineStatus != null) { length += OnlineStatus.Length; }
                    if (Title != null) { length += Title.Length; }
                    return length;
                }
            }

            public MemberDataBlock() { }
            public MemberDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    Contribution = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    OnlineStatus = new byte[length];
                    Buffer.BlockCopy(bytes, i, OnlineStatus, 0, length); i += length;
                    AgentPowers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    length = bytes[i++];
                    Title = new byte[length];
                    Buffer.BlockCopy(bytes, i, Title, 0, length); i += length;
                    IsOwner = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Contribution, bytes, i); i += 4;
                bytes[i++] = (byte)OnlineStatus.Length;
                Buffer.BlockCopy(OnlineStatus, 0, bytes, i, OnlineStatus.Length); i += OnlineStatus.Length;
                Utils.UInt64ToBytes(AgentPowers, bytes, i); i += 8;
                bytes[i++] = (byte)Title.Length;
                Buffer.BlockCopy(Title, 0, bytes, i, Title.Length); i += Title.Length;
                bytes[i++] = (byte)((IsOwner) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += GroupData.Length;
                for (int j = 0; j < MemberData.Length; j++)
                    length += MemberData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public MemberDataBlock[] MemberData;

        public GroupMembersReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupMembersReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 367;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            MemberData = null;
        }

        public GroupMembersReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(MemberData == null || MemberData.Length != -1) {
                MemberData = new MemberDataBlock[count];
                for(int j = 0; j < count; j++)
                { MemberData[j] = new MemberDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MemberData[j].FromBytes(bytes, ref i); }
        }

        public GroupMembersReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(MemberData == null || MemberData.Length != count) {
                MemberData = new MemberDataBlock[count];
                for(int j = 0; j < count; j++)
                { MemberData[j] = new MemberDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MemberData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length++;
            for (int j = 0; j < MemberData.Length; j++) { length += MemberData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)MemberData.Length;
            for (int j = 0; j < MemberData.Length; j++) { MemberData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += GroupData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            GroupData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int MemberDataStart = 0;
            do
            {
                int variableLength = 0;
                int MemberDataCount = 0;

                i = MemberDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < MemberData.Length) {
                    int blockLength = MemberData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++MemberDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)MemberDataCount;
                for (i = MemberDataStart; i < MemberDataStart + MemberDataCount; i++) { MemberData[i].ToBytes(packet, ref length); }
                MemberDataStart += MemberDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                MemberDataStart < MemberData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ActivateGroupPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ActivateGroupPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ActivateGroup;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 368;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
        }

        public ActivateGroupPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ActivateGroupPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SetGroupContributionPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupID;
            public int Contribution;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    Contribution = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Contribution, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public SetGroupContributionPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SetGroupContribution;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 369;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public SetGroupContributionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public SetGroupContributionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SetGroupAcceptNoticesPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public UUID GroupID;
            public bool AcceptNotices;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    AcceptNotices = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((AcceptNotices) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class NewDataBlock : PacketBlock
        {
            public bool ListInProfile;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public NewDataBlock() { }
            public NewDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ListInProfile = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((ListInProfile) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                length += NewData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;
        public NewDataBlock NewData;

        public SetGroupAcceptNoticesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SetGroupAcceptNotices;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 370;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
            NewData = new NewDataBlock();
        }

        public SetGroupAcceptNoticesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            NewData.FromBytes(bytes, ref i);
        }

        public SetGroupAcceptNoticesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
            NewData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            length += NewData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            NewData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupRoleDataRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public UUID RequestID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public GroupRoleDataRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupRoleDataRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 371;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public GroupRoleDataRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public GroupRoleDataRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupRoleDataReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public UUID RequestID;
            public int RoleCount;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                    RoleCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(RoleCount, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RoleDataBlock : PacketBlock
        {
            public UUID RoleID;
            public byte[] Name;
            public byte[] Title;
            public byte[] Description;
            public ulong Powers;
            public uint Members;

            public override int Length
            {
                get
                {
                    int length = 31;
                    if (Name != null) { length += Name.Length; }
                    if (Title != null) { length += Title.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public RoleDataBlock() { }
            public RoleDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RoleID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Title = new byte[length];
                    Buffer.BlockCopy(bytes, i, Title, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    Powers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Members = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RoleID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Title.Length;
                Buffer.BlockCopy(Title, 0, bytes, i, Title.Length); i += Title.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.UInt64ToBytes(Powers, bytes, i); i += 8;
                Utils.UIntToBytes(Members, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += GroupData.Length;
                for (int j = 0; j < RoleData.Length; j++)
                    length += RoleData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;
        public RoleDataBlock[] RoleData;

        public GroupRoleDataReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupRoleDataReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 372;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
            RoleData = null;
        }

        public GroupRoleDataReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RoleData == null || RoleData.Length != -1) {
                RoleData = new RoleDataBlock[count];
                for(int j = 0; j < count; j++)
                { RoleData[j] = new RoleDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RoleData[j].FromBytes(bytes, ref i); }
        }

        public GroupRoleDataReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RoleData == null || RoleData.Length != count) {
                RoleData = new RoleDataBlock[count];
                for(int j = 0; j < count; j++)
                { RoleData[j] = new RoleDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RoleData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            length++;
            for (int j = 0; j < RoleData.Length; j++) { length += RoleData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RoleData.Length;
            for (int j = 0; j < RoleData.Length; j++) { RoleData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += GroupData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            GroupData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RoleDataStart = 0;
            do
            {
                int variableLength = 0;
                int RoleDataCount = 0;

                i = RoleDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RoleData.Length) {
                    int blockLength = RoleData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RoleDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RoleDataCount;
                for (i = RoleDataStart; i < RoleDataStart + RoleDataCount; i++) { RoleData[i].ToBytes(packet, ref length); }
                RoleDataStart += RoleDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RoleDataStart < RoleData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupRoleMembersRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public UUID RequestID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += GroupData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock GroupData;

        public GroupRoleMembersRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupRoleMembersRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 373;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            GroupData = new GroupDataBlock();
        }

        public GroupRoleMembersRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public GroupRoleMembersRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            GroupData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += GroupData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            GroupData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupRoleMembersReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;
            public UUID RequestID;
            public uint TotalPairs;

            public override int Length
            {
                get
                {
                    return 52;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                    TotalPairs = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(TotalPairs, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class MemberDataBlock : PacketBlock
        {
            public UUID RoleID;
            public UUID MemberID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public MemberDataBlock() { }
            public MemberDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RoleID.FromBytes(bytes, i); i += 16;
                    MemberID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RoleID.ToBytes(bytes, i); i += 16;
                MemberID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < MemberData.Length; j++)
                    length += MemberData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public MemberDataBlock[] MemberData;

        public GroupRoleMembersReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupRoleMembersReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 374;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            MemberData = null;
        }

        public GroupRoleMembersReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(MemberData == null || MemberData.Length != -1) {
                MemberData = new MemberDataBlock[count];
                for(int j = 0; j < count; j++)
                { MemberData[j] = new MemberDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MemberData[j].FromBytes(bytes, ref i); }
        }

        public GroupRoleMembersReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(MemberData == null || MemberData.Length != count) {
                MemberData = new MemberDataBlock[count];
                for(int j = 0; j < count; j++)
                { MemberData[j] = new MemberDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { MemberData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < MemberData.Length; j++) { length += MemberData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)MemberData.Length;
            for (int j = 0; j < MemberData.Length; j++) { MemberData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int MemberDataStart = 0;
            do
            {
                int variableLength = 0;
                int MemberDataCount = 0;

                i = MemberDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < MemberData.Length) {
                    int blockLength = MemberData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++MemberDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)MemberDataCount;
                for (i = MemberDataStart; i < MemberDataStart + MemberDataCount; i++) { MemberData[i].ToBytes(packet, ref length); }
                MemberDataStart += MemberDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                MemberDataStart < MemberData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupTitlesRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;
            public UUID RequestID;

            public override int Length
            {
                get
                {
                    return 64;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public GroupTitlesRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupTitlesRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 375;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public GroupTitlesRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public GroupTitlesRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupTitlesReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;
            public UUID RequestID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    RequestID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                RequestID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public byte[] Title;
            public UUID RoleID;
            public bool Selected;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (Title != null) { length += Title.Length; }
                    return length;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Title = new byte[length];
                    Buffer.BlockCopy(bytes, i, Title, 0, length); i += length;
                    RoleID.FromBytes(bytes, i); i += 16;
                    Selected = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Title.Length;
                Buffer.BlockCopy(Title, 0, bytes, i, Title.Length); i += Title.Length;
                RoleID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((Selected) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < GroupData.Length; j++)
                    length += GroupData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock[] GroupData;

        public GroupTitlesReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupTitlesReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 376;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = null;
        }

        public GroupTitlesReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != -1) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
        }

        public GroupTitlesReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != count) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < GroupData.Length; j++) { length += GroupData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)GroupData.Length;
            for (int j = 0; j < GroupData.Length; j++) { GroupData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int GroupDataStart = 0;
            do
            {
                int variableLength = 0;
                int GroupDataCount = 0;

                i = GroupDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < GroupData.Length) {
                    int blockLength = GroupData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++GroupDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)GroupDataCount;
                for (i = GroupDataStart; i < GroupDataStart + GroupDataCount; i++) { GroupData[i].ToBytes(packet, ref length); }
                GroupDataStart += GroupDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                GroupDataStart < GroupData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class GroupTitleUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;
            public UUID TitleRoleID;

            public override int Length
            {
                get
                {
                    return 64;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    TitleRoleID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                TitleRoleID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public GroupTitleUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.GroupTitleUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 377;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public GroupTitleUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public GroupTitleUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupRoleUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RoleDataBlock : PacketBlock
        {
            public UUID RoleID;
            public byte[] Name;
            public byte[] Description;
            public byte[] Title;
            public ulong Powers;
            public byte UpdateType;

            public override int Length
            {
                get
                {
                    int length = 28;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    if (Title != null) { length += Title.Length; }
                    return length;
                }
            }

            public RoleDataBlock() { }
            public RoleDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RoleID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    length = bytes[i++];
                    Title = new byte[length];
                    Buffer.BlockCopy(bytes, i, Title, 0, length); i += length;
                    Powers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    UpdateType = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RoleID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                bytes[i++] = (byte)Title.Length;
                Buffer.BlockCopy(Title, 0, bytes, i, Title.Length); i += Title.Length;
                Utils.UInt64ToBytes(Powers, bytes, i); i += 8;
                bytes[i++] = UpdateType;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < RoleData.Length; j++)
                    length += RoleData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RoleDataBlock[] RoleData;

        public GroupRoleUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupRoleUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 378;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RoleData = null;
        }

        public GroupRoleUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RoleData == null || RoleData.Length != -1) {
                RoleData = new RoleDataBlock[count];
                for(int j = 0; j < count; j++)
                { RoleData[j] = new RoleDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RoleData[j].FromBytes(bytes, ref i); }
        }

        public GroupRoleUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RoleData == null || RoleData.Length != count) {
                RoleData = new RoleDataBlock[count];
                for(int j = 0; j < count; j++)
                { RoleData[j] = new RoleDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RoleData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < RoleData.Length; j++) { length += RoleData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RoleData.Length;
            for (int j = 0; j < RoleData.Length; j++) { RoleData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RoleDataStart = 0;
            do
            {
                int variableLength = 0;
                int RoleDataCount = 0;

                i = RoleDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RoleData.Length) {
                    int blockLength = RoleData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RoleDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RoleDataCount;
                for (i = RoleDataStart; i < RoleDataStart + RoleDataCount; i++) { RoleData[i].ToBytes(packet, ref length); }
                RoleDataStart += RoleDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RoleDataStart < RoleData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class LiveHelpGroupRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class RequestDataBlock : PacketBlock
        {
            public UUID RequestID;
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public RequestDataBlock() { }
            public RequestDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += RequestData.Length;
                return length;
            }
        }
        public RequestDataBlock RequestData;

        public LiveHelpGroupRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LiveHelpGroupRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 379;
            Header.Reliable = true;
            RequestData = new RequestDataBlock();
        }

        public LiveHelpGroupRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RequestData.FromBytes(bytes, ref i);
        }

        public LiveHelpGroupRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RequestData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += RequestData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RequestData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LiveHelpGroupReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class ReplyDataBlock : PacketBlock
        {
            public UUID RequestID;
            public UUID GroupID;
            public byte[] Selection;

            public override int Length
            {
                get
                {
                    int length = 33;
                    if (Selection != null) { length += Selection.Length; }
                    return length;
                }
            }

            public ReplyDataBlock() { }
            public ReplyDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RequestID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Selection = new byte[length];
                    Buffer.BlockCopy(bytes, i, Selection, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                RequestID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Selection.Length;
                Buffer.BlockCopy(Selection, 0, bytes, i, Selection.Length); i += Selection.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ReplyData.Length;
                return length;
            }
        }
        public ReplyDataBlock ReplyData;

        public LiveHelpGroupReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LiveHelpGroupReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 380;
            Header.Reliable = true;
            ReplyData = new ReplyDataBlock();
        }

        public LiveHelpGroupReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ReplyData.FromBytes(bytes, ref i);
        }

        public LiveHelpGroupReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ReplyData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ReplyData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ReplyData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentWearablesRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentWearablesRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentWearablesRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 381;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public AgentWearablesRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentWearablesRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentWearablesUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint SerialNum;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    SerialNum = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(SerialNum, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class WearableDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID AssetID;
            public byte WearableType;

            public override int Length
            {
                get
                {
                    return 33;
                }
            }

            public WearableDataBlock() { }
            public WearableDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    AssetID.FromBytes(bytes, i); i += 16;
                    WearableType = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                AssetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = WearableType;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < WearableData.Length; j++)
                    length += WearableData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public WearableDataBlock[] WearableData;

        public AgentWearablesUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentWearablesUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 382;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            WearableData = null;
        }

        public AgentWearablesUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != -1) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public AgentWearablesUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != count) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < WearableData.Length; j++) { length += WearableData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)WearableData.Length;
            for (int j = 0; j < WearableData.Length; j++) { WearableData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int WearableDataStart = 0;
            do
            {
                int variableLength = 0;
                int WearableDataCount = 0;

                i = WearableDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < WearableData.Length) {
                    int blockLength = WearableData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++WearableDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)WearableDataCount;
                for (i = WearableDataStart; i < WearableDataStart + WearableDataCount; i++) { WearableData[i].ToBytes(packet, ref length); }
                WearableDataStart += WearableDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                WearableDataStart < WearableData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentIsNowWearingPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class WearableDataBlock : PacketBlock
        {
            public UUID ItemID;
            public byte WearableType;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public WearableDataBlock() { }
            public WearableDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    WearableType = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                bytes[i++] = WearableType;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < WearableData.Length; j++)
                    length += WearableData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public WearableDataBlock[] WearableData;

        public AgentIsNowWearingPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentIsNowWearing;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 383;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            WearableData = null;
        }

        public AgentIsNowWearingPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != -1) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public AgentIsNowWearingPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != count) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < WearableData.Length; j++) { length += WearableData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)WearableData.Length;
            for (int j = 0; j < WearableData.Length; j++) { WearableData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int WearableDataStart = 0;
            do
            {
                int variableLength = 0;
                int WearableDataCount = 0;

                i = WearableDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < WearableData.Length) {
                    int blockLength = WearableData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++WearableDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)WearableDataCount;
                for (i = WearableDataStart; i < WearableDataStart + WearableDataCount; i++) { WearableData[i].ToBytes(packet, ref length); }
                WearableDataStart += WearableDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                WearableDataStart < WearableData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentCachedTexturePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public int SerialNum;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    SerialNum = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(SerialNum, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class WearableDataBlock : PacketBlock
        {
            public UUID ID;
            public byte TextureIndex;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public WearableDataBlock() { }
            public WearableDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    TextureIndex = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = TextureIndex;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < WearableData.Length; j++)
                    length += WearableData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public WearableDataBlock[] WearableData;

        public AgentCachedTexturePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentCachedTexture;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 384;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            WearableData = null;
        }

        public AgentCachedTexturePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != -1) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public AgentCachedTexturePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != count) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < WearableData.Length; j++) { length += WearableData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)WearableData.Length;
            for (int j = 0; j < WearableData.Length; j++) { WearableData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int WearableDataStart = 0;
            do
            {
                int variableLength = 0;
                int WearableDataCount = 0;

                i = WearableDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < WearableData.Length) {
                    int blockLength = WearableData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++WearableDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)WearableDataCount;
                for (i = WearableDataStart; i < WearableDataStart + WearableDataCount; i++) { WearableData[i].ToBytes(packet, ref length); }
                WearableDataStart += WearableDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                WearableDataStart < WearableData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentCachedTextureResponsePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public int SerialNum;

            public override int Length
            {
                get
                {
                    return 36;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    SerialNum = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(SerialNum, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class WearableDataBlock : PacketBlock
        {
            public UUID TextureID;
            public byte TextureIndex;
            public byte[] HostName;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (HostName != null) { length += HostName.Length; }
                    return length;
                }
            }

            public WearableDataBlock() { }
            public WearableDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TextureID.FromBytes(bytes, i); i += 16;
                    TextureIndex = (byte)bytes[i++];
                    length = bytes[i++];
                    HostName = new byte[length];
                    Buffer.BlockCopy(bytes, i, HostName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TextureID.ToBytes(bytes, i); i += 16;
                bytes[i++] = TextureIndex;
                bytes[i++] = (byte)HostName.Length;
                Buffer.BlockCopy(HostName, 0, bytes, i, HostName.Length); i += HostName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < WearableData.Length; j++)
                    length += WearableData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public WearableDataBlock[] WearableData;

        public AgentCachedTextureResponsePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentCachedTextureResponse;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 385;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            WearableData = null;
        }

        public AgentCachedTextureResponsePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != -1) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public AgentCachedTextureResponsePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(WearableData == null || WearableData.Length != count) {
                WearableData = new WearableDataBlock[count];
                for(int j = 0; j < count; j++)
                { WearableData[j] = new WearableDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { WearableData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < WearableData.Length; j++) { length += WearableData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)WearableData.Length;
            for (int j = 0; j < WearableData.Length; j++) { WearableData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int WearableDataStart = 0;
            do
            {
                int variableLength = 0;
                int WearableDataCount = 0;

                i = WearableDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < WearableData.Length) {
                    int blockLength = WearableData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++WearableDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)WearableDataCount;
                for (i = WearableDataStart; i < WearableDataStart + WearableDataCount; i++) { WearableData[i].ToBytes(packet, ref length); }
                WearableDataStart += WearableDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                WearableDataStart < WearableData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentDataUpdateRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentDataUpdateRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentDataUpdateRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 386;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public AgentDataUpdateRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentDataUpdateRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentDataUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public byte[] FirstName;
            public byte[] LastName;
            public byte[] GroupTitle;
            public UUID ActiveGroupID;
            public ulong GroupPowers;
            public byte[] GroupName;

            public override int Length
            {
                get
                {
                    int length = 44;
                    if (FirstName != null) { length += FirstName.Length; }
                    if (LastName != null) { length += LastName.Length; }
                    if (GroupTitle != null) { length += GroupTitle.Length; }
                    if (GroupName != null) { length += GroupName.Length; }
                    return length;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    FirstName = new byte[length];
                    Buffer.BlockCopy(bytes, i, FirstName, 0, length); i += length;
                    length = bytes[i++];
                    LastName = new byte[length];
                    Buffer.BlockCopy(bytes, i, LastName, 0, length); i += length;
                    length = bytes[i++];
                    GroupTitle = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupTitle, 0, length); i += length;
                    ActiveGroupID.FromBytes(bytes, i); i += 16;
                    GroupPowers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    length = bytes[i++];
                    GroupName = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)FirstName.Length;
                Buffer.BlockCopy(FirstName, 0, bytes, i, FirstName.Length); i += FirstName.Length;
                bytes[i++] = (byte)LastName.Length;
                Buffer.BlockCopy(LastName, 0, bytes, i, LastName.Length); i += LastName.Length;
                bytes[i++] = (byte)GroupTitle.Length;
                Buffer.BlockCopy(GroupTitle, 0, bytes, i, GroupTitle.Length); i += GroupTitle.Length;
                ActiveGroupID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(GroupPowers, bytes, i); i += 8;
                bytes[i++] = (byte)GroupName.Length;
                Buffer.BlockCopy(GroupName, 0, bytes, i, GroupName.Length); i += GroupName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentDataUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentDataUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 387;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
        }

        public AgentDataUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentDataUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class GroupDataUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentGroupDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;
            public ulong AgentPowers;
            public byte[] GroupTitle;

            public override int Length
            {
                get
                {
                    int length = 41;
                    if (GroupTitle != null) { length += GroupTitle.Length; }
                    return length;
                }
            }

            public AgentGroupDataBlock() { }
            public AgentGroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    AgentPowers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    length = bytes[i++];
                    GroupTitle = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupTitle, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(AgentPowers, bytes, i); i += 8;
                bytes[i++] = (byte)GroupTitle.Length;
                Buffer.BlockCopy(GroupTitle, 0, bytes, i, GroupTitle.Length); i += GroupTitle.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < AgentGroupData.Length; j++)
                    length += AgentGroupData[j].Length;
                return length;
            }
        }
        public AgentGroupDataBlock[] AgentGroupData;

        public GroupDataUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.GroupDataUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 388;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentGroupData = null;
        }

        public GroupDataUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(AgentGroupData == null || AgentGroupData.Length != -1) {
                AgentGroupData = new AgentGroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { AgentGroupData[j] = new AgentGroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentGroupData[j].FromBytes(bytes, ref i); }
        }

        public GroupDataUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(AgentGroupData == null || AgentGroupData.Length != count) {
                AgentGroupData = new AgentGroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { AgentGroupData[j] = new AgentGroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentGroupData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < AgentGroupData.Length; j++) { length += AgentGroupData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AgentGroupData.Length;
            for (int j = 0; j < AgentGroupData.Length; j++) { AgentGroupData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int AgentGroupDataStart = 0;
            do
            {
                int variableLength = 0;
                int AgentGroupDataCount = 0;

                i = AgentGroupDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AgentGroupData.Length) {
                    int blockLength = AgentGroupData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AgentGroupDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AgentGroupDataCount;
                for (i = AgentGroupDataStart; i < AgentGroupDataStart + AgentGroupDataCount; i++) { AgentGroupData[i].ToBytes(packet, ref length); }
                AgentGroupDataStart += AgentGroupDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AgentGroupDataStart < AgentGroupData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentGroupDataUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public ulong GroupPowers;
            public bool AcceptNotices;
            public UUID GroupInsigniaID;
            public int Contribution;
            public byte[] GroupName;

            public override int Length
            {
                get
                {
                    int length = 46;
                    if (GroupName != null) { length += GroupName.Length; }
                    return length;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    GroupPowers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    AcceptNotices = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    GroupInsigniaID.FromBytes(bytes, i); i += 16;
                    Contribution = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    GroupName = new byte[length];
                    Buffer.BlockCopy(bytes, i, GroupName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(GroupPowers, bytes, i); i += 8;
                bytes[i++] = (byte)((AcceptNotices) ? 1 : 0);
                GroupInsigniaID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Contribution, bytes, i); i += 4;
                bytes[i++] = (byte)GroupName.Length;
                Buffer.BlockCopy(GroupName, 0, bytes, i, GroupName.Length); i += GroupName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < GroupData.Length; j++)
                    length += GroupData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock[] GroupData;

        public AgentGroupDataUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentGroupDataUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 389;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = null;
        }

        public AgentGroupDataUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != -1) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
        }

        public AgentGroupDataUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != count) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < GroupData.Length; j++) { length += GroupData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)GroupData.Length;
            for (int j = 0; j < GroupData.Length; j++) { GroupData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int GroupDataStart = 0;
            do
            {
                int variableLength = 0;
                int GroupDataCount = 0;

                i = GroupDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < GroupData.Length) {
                    int blockLength = GroupData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++GroupDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)GroupDataCount;
                for (i = GroupDataStart; i < GroupDataStart + GroupDataCount; i++) { GroupData[i].ToBytes(packet, ref length); }
                GroupDataStart += GroupDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                GroupDataStart < GroupData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentDropGroupPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentDropGroupPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentDropGroup;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 390;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
        }

        public AgentDropGroupPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentDropGroupPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RezSingleAttachmentFromInvPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID OwnerID;
            public byte AttachmentPt;
            public uint ItemFlags;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public byte[] Name;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 51;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    AttachmentPt = (byte)bytes[i++];
                    ItemFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = AttachmentPt;
                Utils.UIntToBytes(ItemFlags, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += ObjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;

        public RezSingleAttachmentFromInvPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RezSingleAttachmentFromInv;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 395;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
        }

        public RezSingleAttachmentFromInvPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public RezSingleAttachmentFromInvPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RezMultipleAttachmentsFromInvPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class HeaderDataBlock : PacketBlock
        {
            public UUID CompoundMsgID;
            public byte TotalObjects;
            public bool FirstDetachAll;

            public override int Length
            {
                get
                {
                    return 18;
                }
            }

            public HeaderDataBlock() { }
            public HeaderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    CompoundMsgID.FromBytes(bytes, i); i += 16;
                    TotalObjects = (byte)bytes[i++];
                    FirstDetachAll = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                CompoundMsgID.ToBytes(bytes, i); i += 16;
                bytes[i++] = TotalObjects;
                bytes[i++] = (byte)((FirstDetachAll) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID OwnerID;
            public byte AttachmentPt;
            public uint ItemFlags;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public byte[] Name;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 51;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    AttachmentPt = (byte)bytes[i++];
                    ItemFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = AttachmentPt;
                Utils.UIntToBytes(ItemFlags, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += HeaderData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public HeaderDataBlock HeaderData;
        public ObjectDataBlock[] ObjectData;

        public RezMultipleAttachmentsFromInvPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RezMultipleAttachmentsFromInv;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 396;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            HeaderData = new HeaderDataBlock();
            ObjectData = null;
        }

        public RezMultipleAttachmentsFromInvPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public RezMultipleAttachmentsFromInvPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += HeaderData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            HeaderData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += HeaderData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            HeaderData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class DetachAttachmentIntoInvPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID ItemID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    ItemID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                ItemID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += ObjectData.Length;
                return length;
            }
        }
        public ObjectDataBlock ObjectData;

        public DetachAttachmentIntoInvPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.DetachAttachmentIntoInv;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 397;
            Header.Reliable = true;
            ObjectData = new ObjectDataBlock();
        }

        public DetachAttachmentIntoInvPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ObjectData.FromBytes(bytes, ref i);
        }

        public DetachAttachmentIntoInvPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CreateNewOutfitAttachmentsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class HeaderDataBlock : PacketBlock
        {
            public UUID NewFolderID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public HeaderDataBlock() { }
            public HeaderDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    NewFolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                NewFolderID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID OldItemID;
            public UUID OldFolderID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    OldItemID.FromBytes(bytes, i); i += 16;
                    OldFolderID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                OldItemID.ToBytes(bytes, i); i += 16;
                OldFolderID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += HeaderData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public HeaderDataBlock HeaderData;
        public ObjectDataBlock[] ObjectData;

        public CreateNewOutfitAttachmentsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.CreateNewOutfitAttachments;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 398;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            HeaderData = new HeaderDataBlock();
            ObjectData = null;
        }

        public CreateNewOutfitAttachmentsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public CreateNewOutfitAttachmentsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            HeaderData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += HeaderData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            HeaderData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += HeaderData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            HeaderData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class UserInfoRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public UserInfoRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UserInfoRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 399;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public UserInfoRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public UserInfoRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UserInfoReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class UserDataBlock : PacketBlock
        {
            public bool IMViaEMail;
            public byte[] DirectoryVisibility;
            public byte[] EMail;

            public override int Length
            {
                get
                {
                    int length = 4;
                    if (DirectoryVisibility != null) { length += DirectoryVisibility.Length; }
                    if (EMail != null) { length += EMail.Length; }
                    return length;
                }
            }

            public UserDataBlock() { }
            public UserDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    IMViaEMail = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    DirectoryVisibility = new byte[length];
                    Buffer.BlockCopy(bytes, i, DirectoryVisibility, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    EMail = new byte[length];
                    Buffer.BlockCopy(bytes, i, EMail, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((IMViaEMail) ? 1 : 0);
                bytes[i++] = (byte)DirectoryVisibility.Length;
                Buffer.BlockCopy(DirectoryVisibility, 0, bytes, i, DirectoryVisibility.Length); i += DirectoryVisibility.Length;
                bytes[i++] = (byte)(EMail.Length % 256);
                bytes[i++] = (byte)((EMail.Length >> 8) % 256);
                Buffer.BlockCopy(EMail, 0, bytes, i, EMail.Length); i += EMail.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += UserData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public UserDataBlock UserData;

        public UserInfoReplyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UserInfoReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 400;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            UserData = new UserDataBlock();
        }

        public UserInfoReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            UserData.FromBytes(bytes, ref i);
        }

        public UserInfoReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            UserData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += UserData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            UserData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class UpdateUserInfoPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class UserDataBlock : PacketBlock
        {
            public bool IMViaEMail;
            public byte[] DirectoryVisibility;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (DirectoryVisibility != null) { length += DirectoryVisibility.Length; }
                    return length;
                }
            }

            public UserDataBlock() { }
            public UserDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    IMViaEMail = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    length = bytes[i++];
                    DirectoryVisibility = new byte[length];
                    Buffer.BlockCopy(bytes, i, DirectoryVisibility, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((IMViaEMail) ? 1 : 0);
                bytes[i++] = (byte)DirectoryVisibility.Length;
                Buffer.BlockCopy(DirectoryVisibility, 0, bytes, i, DirectoryVisibility.Length); i += DirectoryVisibility.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += UserData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public UserDataBlock UserData;

        public UpdateUserInfoPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.UpdateUserInfo;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 401;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            UserData = new UserDataBlock();
        }

        public UpdateUserInfoPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            UserData.FromBytes(bytes, ref i);
        }

        public UpdateUserInfoPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            UserData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += UserData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            UserData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class InitiateDownloadPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class FileDataBlock : PacketBlock
        {
            public byte[] SimFilename;
            public byte[] ViewerFilename;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (SimFilename != null) { length += SimFilename.Length; }
                    if (ViewerFilename != null) { length += ViewerFilename.Length; }
                    return length;
                }
            }

            public FileDataBlock() { }
            public FileDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    SimFilename = new byte[length];
                    Buffer.BlockCopy(bytes, i, SimFilename, 0, length); i += length;
                    length = bytes[i++];
                    ViewerFilename = new byte[length];
                    Buffer.BlockCopy(bytes, i, ViewerFilename, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)SimFilename.Length;
                Buffer.BlockCopy(SimFilename, 0, bytes, i, SimFilename.Length); i += SimFilename.Length;
                bytes[i++] = (byte)ViewerFilename.Length;
                Buffer.BlockCopy(ViewerFilename, 0, bytes, i, ViewerFilename.Length); i += ViewerFilename.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += FileData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public FileDataBlock FileData;

        public InitiateDownloadPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.InitiateDownload;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 403;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            FileData = new FileDataBlock();
        }

        public InitiateDownloadPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            FileData.FromBytes(bytes, ref i);
        }

        public InitiateDownloadPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            FileData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += FileData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            FileData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MapLayerRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint Flags;
            public uint EstateID;
            public bool Godlike;

            public override int Length
            {
                get
                {
                    return 41;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Godlike = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.UIntToBytes(EstateID, bytes, i); i += 4;
                bytes[i++] = (byte)((Godlike) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public MapLayerRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MapLayerRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 405;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public MapLayerRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public MapLayerRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MapLayerReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class LayerDataBlock : PacketBlock
        {
            public uint Left;
            public uint Right;
            public uint Top;
            public uint Bottom;
            public UUID ImageID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public LayerDataBlock() { }
            public LayerDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Left = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Right = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Top = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Bottom = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ImageID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Left, bytes, i); i += 4;
                Utils.UIntToBytes(Right, bytes, i); i += 4;
                Utils.UIntToBytes(Top, bytes, i); i += 4;
                Utils.UIntToBytes(Bottom, bytes, i); i += 4;
                ImageID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < LayerData.Length; j++)
                    length += LayerData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public LayerDataBlock[] LayerData;

        public MapLayerReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MapLayerReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 406;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            LayerData = null;
        }

        public MapLayerReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(LayerData == null || LayerData.Length != -1) {
                LayerData = new LayerDataBlock[count];
                for(int j = 0; j < count; j++)
                { LayerData[j] = new LayerDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { LayerData[j].FromBytes(bytes, ref i); }
        }

        public MapLayerReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(LayerData == null || LayerData.Length != count) {
                LayerData = new LayerDataBlock[count];
                for(int j = 0; j < count; j++)
                { LayerData[j] = new LayerDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { LayerData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < LayerData.Length; j++) { length += LayerData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)LayerData.Length;
            for (int j = 0; j < LayerData.Length; j++) { LayerData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int LayerDataStart = 0;
            do
            {
                int variableLength = 0;
                int LayerDataCount = 0;

                i = LayerDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < LayerData.Length) {
                    int blockLength = LayerData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++LayerDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)LayerDataCount;
                for (i = LayerDataStart; i < LayerDataStart + LayerDataCount; i++) { LayerData[i].ToBytes(packet, ref length); }
                LayerDataStart += LayerDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                LayerDataStart < LayerData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class MapBlockRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint Flags;
            public uint EstateID;
            public bool Godlike;

            public override int Length
            {
                get
                {
                    return 41;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Godlike = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.UIntToBytes(EstateID, bytes, i); i += 4;
                bytes[i++] = (byte)((Godlike) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class PositionDataBlock : PacketBlock
        {
            public ushort MinX;
            public ushort MaxX;
            public ushort MinY;
            public ushort MaxY;

            public override int Length
            {
                get
                {
                    return 8;
                }
            }

            public PositionDataBlock() { }
            public PositionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    MinX = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    MaxX = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    MinY = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    MaxY = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(MinX % 256);
                bytes[i++] = (byte)((MinX >> 8) % 256);
                bytes[i++] = (byte)(MaxX % 256);
                bytes[i++] = (byte)((MaxX >> 8) % 256);
                bytes[i++] = (byte)(MinY % 256);
                bytes[i++] = (byte)((MinY >> 8) % 256);
                bytes[i++] = (byte)(MaxY % 256);
                bytes[i++] = (byte)((MaxY >> 8) % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += PositionData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public PositionDataBlock PositionData;

        public MapBlockRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MapBlockRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 407;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            PositionData = new PositionDataBlock();
        }

        public MapBlockRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            PositionData.FromBytes(bytes, ref i);
        }

        public MapBlockRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            PositionData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += PositionData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            PositionData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MapNameRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint Flags;
            public uint EstateID;
            public bool Godlike;

            public override int Length
            {
                get
                {
                    return 41;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Godlike = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.UIntToBytes(EstateID, bytes, i); i += 4;
                bytes[i++] = (byte)((Godlike) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class NameDataBlock : PacketBlock
        {
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public NameDataBlock() { }
            public NameDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += NameData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public NameDataBlock NameData;

        public MapNameRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MapNameRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 408;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            NameData = new NameDataBlock();
        }

        public MapNameRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            NameData.FromBytes(bytes, ref i);
        }

        public MapNameRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            NameData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += NameData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            NameData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MapBlockReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public ushort X;
            public ushort Y;
            public byte[] Name;
            public byte Access;
            public uint RegionFlags;
            public byte WaterHeight;
            public byte Agents;
            public UUID MapImageID;

            public override int Length
            {
                get
                {
                    int length = 28;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    X = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    Y = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    Access = (byte)bytes[i++];
                    RegionFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    WaterHeight = (byte)bytes[i++];
                    Agents = (byte)bytes[i++];
                    MapImageID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(X % 256);
                bytes[i++] = (byte)((X >> 8) % 256);
                bytes[i++] = (byte)(Y % 256);
                bytes[i++] = (byte)((Y >> 8) % 256);
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = Access;
                Utils.UIntToBytes(RegionFlags, bytes, i); i += 4;
                bytes[i++] = WaterHeight;
                bytes[i++] = Agents;
                MapImageID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class SizeBlock : PacketBlock
        {
            public ushort SizeX;
            public ushort SizeY;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public SizeBlock() { }
            public SizeBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SizeX = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    SizeY = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(SizeX % 256);
                bytes[i++] = (byte)((SizeX >> 8) % 256);
                bytes[i++] = (byte)(SizeY % 256);
                bytes[i++] = (byte)((SizeY >> 8) % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 12;
                length += AgentData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                for (int j = 0; j < Size.Length; j++)
                    length += Size[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock[] Data;
        public SizeBlock[] Size;

        public MapBlockReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MapBlockReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 409;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            Data = null;
            Size = null;
        }

        public MapBlockReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(Size == null || Size.Length != -1) {
                Size = new SizeBlock[count];
                for(int j = 0; j < count; j++)
                { Size[j] = new SizeBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Size[j].FromBytes(bytes, ref i); }
        }

        public MapBlockReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(Size == null || Size.Length != count) {
                Size = new SizeBlock[count];
                for(int j = 0; j < count; j++)
                { Size[j] = new SizeBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Size[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            length++;
            for (int j = 0; j < Size.Length; j++) { length += Size[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)Size.Length;
            for (int j = 0; j < Size.Length; j++) { Size[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int DataStart = 0;
            int SizeStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;
                int SizeCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = SizeStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Size.Length) {
                    int blockLength = Size[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++SizeCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                packet[length++] = (byte)SizeCount;
                for (i = SizeStart; i < SizeStart + SizeCount; i++) { Size[i].ToBytes(packet, ref length); }
                SizeStart += SizeCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length ||
                SizeStart < Size.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class MapItemRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public uint Flags;
            public uint EstateID;
            public bool Godlike;

            public override int Length
            {
                get
                {
                    return 41;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EstateID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Godlike = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.UIntToBytes(EstateID, bytes, i); i += 4;
                bytes[i++] = (byte)((Godlike) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class RequestDataBlock : PacketBlock
        {
            public uint ItemType;
            public ulong RegionHandle;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public RequestDataBlock() { }
            public RequestDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ItemType, bytes, i); i += 4;
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += RequestData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RequestDataBlock RequestData;

        public MapItemRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.MapItemRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 410;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RequestData = new RequestDataBlock();
        }

        public MapItemRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RequestData.FromBytes(bytes, ref i);
        }

        public MapItemRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RequestData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RequestData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RequestData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MapItemReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class RequestDataBlock : PacketBlock
        {
            public uint ItemType;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public RequestDataBlock() { }
            public RequestDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ItemType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ItemType, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public uint X;
            public uint Y;
            public UUID ID;
            public int Extra;
            public int Extra2;
            public byte[] Name;

            public override int Length
            {
                get
                {
                    int length = 33;
                    if (Name != null) { length += Name.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    X = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Y = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ID.FromBytes(bytes, i); i += 16;
                    Extra = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Extra2 = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(X, bytes, i); i += 4;
                Utils.UIntToBytes(Y, bytes, i); i += 4;
                ID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(Extra, bytes, i); i += 4;
                Utils.IntToBytes(Extra2, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                length += RequestData.Length;
                for (int j = 0; j < Data.Length; j++)
                    length += Data[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RequestDataBlock RequestData;
        public DataBlock[] Data;

        public MapItemReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MapItemReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 411;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RequestData = new RequestDataBlock();
            Data = null;
        }

        public MapItemReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RequestData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != -1) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public MapItemReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RequestData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Data == null || Data.Length != count) {
                Data = new DataBlock[count];
                for(int j = 0; j < count; j++)
                { Data[j] = new DataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Data[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RequestData.Length;
            length++;
            for (int j = 0; j < Data.Length; j++) { length += Data[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RequestData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Data.Length;
            for (int j = 0; j < Data.Length; j++) { Data[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            fixedLength += RequestData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            RequestData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataStart = 0;
            do
            {
                int variableLength = 0;
                int DataCount = 0;

                i = DataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Data.Length) {
                    int blockLength = Data[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataCount;
                for (i = DataStart; i < DataStart + DataCount; i++) { Data[i].ToBytes(packet, ref length); }
                DataStart += DataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataStart < Data.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class SendPostcardPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID AssetID;
            public Vector3d PosGlobal;
            public byte[] To;
            public byte[] From;
            public byte[] Name;
            public byte[] Subject;
            public byte[] Msg;
            public bool AllowPublish;
            public bool MaturePublish;

            public override int Length
            {
                get
                {
                    int length = 80;
                    if (To != null) { length += To.Length; }
                    if (From != null) { length += From.Length; }
                    if (Name != null) { length += Name.Length; }
                    if (Subject != null) { length += Subject.Length; }
                    if (Msg != null) { length += Msg.Length; }
                    return length;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    AssetID.FromBytes(bytes, i); i += 16;
                    PosGlobal.FromBytes(bytes, i); i += 24;
                    length = bytes[i++];
                    To = new byte[length];
                    Buffer.BlockCopy(bytes, i, To, 0, length); i += length;
                    length = bytes[i++];
                    From = new byte[length];
                    Buffer.BlockCopy(bytes, i, From, 0, length); i += length;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Subject = new byte[length];
                    Buffer.BlockCopy(bytes, i, Subject, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Msg = new byte[length];
                    Buffer.BlockCopy(bytes, i, Msg, 0, length); i += length;
                    AllowPublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    MaturePublish = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                AssetID.ToBytes(bytes, i); i += 16;
                PosGlobal.ToBytes(bytes, i); i += 24;
                bytes[i++] = (byte)To.Length;
                Buffer.BlockCopy(To, 0, bytes, i, To.Length); i += To.Length;
                bytes[i++] = (byte)From.Length;
                Buffer.BlockCopy(From, 0, bytes, i, From.Length); i += From.Length;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Subject.Length;
                Buffer.BlockCopy(Subject, 0, bytes, i, Subject.Length); i += Subject.Length;
                bytes[i++] = (byte)(Msg.Length % 256);
                bytes[i++] = (byte)((Msg.Length >> 8) % 256);
                Buffer.BlockCopy(Msg, 0, bytes, i, Msg.Length); i += Msg.Length;
                bytes[i++] = (byte)((AllowPublish) ? 1 : 0);
                bytes[i++] = (byte)((MaturePublish) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public SendPostcardPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SendPostcard;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 412;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public SendPostcardPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public SendPostcardPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelMediaCommandMessagePacket : Packet
    {
        /// <exclude/>
        public sealed class CommandBlockBlock : PacketBlock
        {
            public uint Flags;
            public uint Command;
            public float Time;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public CommandBlockBlock() { }
            public CommandBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Command = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Time = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                Utils.UIntToBytes(Command, bytes, i); i += 4;
                Utils.FloatToBytes(Time, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += CommandBlock.Length;
                return length;
            }
        }
        public CommandBlockBlock CommandBlock;

        public ParcelMediaCommandMessagePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelMediaCommandMessage;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 419;
            Header.Reliable = true;
            CommandBlock = new CommandBlockBlock();
        }

        public ParcelMediaCommandMessagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            CommandBlock.FromBytes(bytes, ref i);
        }

        public ParcelMediaCommandMessagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            CommandBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += CommandBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            CommandBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelMediaUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlockBlock : PacketBlock
        {
            public byte[] MediaURL;
            public UUID MediaID;
            public byte MediaAutoScale;

            public override int Length
            {
                get
                {
                    int length = 18;
                    if (MediaURL != null) { length += MediaURL.Length; }
                    return length;
                }
            }

            public DataBlockBlock() { }
            public DataBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    MediaURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaURL, 0, length); i += length;
                    MediaID.FromBytes(bytes, i); i += 16;
                    MediaAutoScale = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)MediaURL.Length;
                Buffer.BlockCopy(MediaURL, 0, bytes, i, MediaURL.Length); i += MediaURL.Length;
                MediaID.ToBytes(bytes, i); i += 16;
                bytes[i++] = MediaAutoScale;
            }

        }

        /// <exclude/>
        public sealed class DataBlockExtendedBlock : PacketBlock
        {
            public byte[] MediaType;
            public byte[] MediaDesc;
            public int MediaWidth;
            public int MediaHeight;
            public byte MediaLoop;

            public override int Length
            {
                get
                {
                    int length = 11;
                    if (MediaType != null) { length += MediaType.Length; }
                    if (MediaDesc != null) { length += MediaDesc.Length; }
                    return length;
                }
            }

            public DataBlockExtendedBlock() { }
            public DataBlockExtendedBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    MediaType = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaType, 0, length); i += length;
                    length = bytes[i++];
                    MediaDesc = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaDesc, 0, length); i += length;
                    MediaWidth = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    MediaHeight = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    MediaLoop = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)MediaType.Length;
                Buffer.BlockCopy(MediaType, 0, bytes, i, MediaType.Length); i += MediaType.Length;
                bytes[i++] = (byte)MediaDesc.Length;
                Buffer.BlockCopy(MediaDesc, 0, bytes, i, MediaDesc.Length); i += MediaDesc.Length;
                Utils.IntToBytes(MediaWidth, bytes, i); i += 4;
                Utils.IntToBytes(MediaHeight, bytes, i); i += 4;
                bytes[i++] = MediaLoop;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += DataBlock.Length;
                length += DataBlockExtended.Length;
                return length;
            }
        }
        public DataBlockBlock DataBlock;
        public DataBlockExtendedBlock DataBlockExtended;

        public ParcelMediaUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelMediaUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 420;
            Header.Reliable = true;
            DataBlock = new DataBlockBlock();
            DataBlockExtended = new DataBlockExtendedBlock();
        }

        public ParcelMediaUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            DataBlock.FromBytes(bytes, ref i);
            DataBlockExtended.FromBytes(bytes, ref i);
        }

        public ParcelMediaUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            DataBlock.FromBytes(bytes, ref i);
            DataBlockExtended.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += DataBlock.Length;
            length += DataBlockExtended.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            DataBlock.ToBytes(bytes, ref i);
            DataBlockExtended.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LandStatRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RequestDataBlock : PacketBlock
        {
            public uint ReportType;
            public uint RequestFlags;
            public byte[] Filter;
            public int ParcelLocalID;

            public override int Length
            {
                get
                {
                    int length = 13;
                    if (Filter != null) { length += Filter.Length; }
                    return length;
                }
            }

            public RequestDataBlock() { }
            public RequestDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ReportType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RequestFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Filter = new byte[length];
                    Buffer.BlockCopy(bytes, i, Filter, 0, length); i += length;
                    ParcelLocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ReportType, bytes, i); i += 4;
                Utils.UIntToBytes(RequestFlags, bytes, i); i += 4;
                bytes[i++] = (byte)Filter.Length;
                Buffer.BlockCopy(Filter, 0, bytes, i, Filter.Length); i += Filter.Length;
                Utils.IntToBytes(ParcelLocalID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += RequestData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RequestDataBlock RequestData;

        public LandStatRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LandStatRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 421;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RequestData = new RequestDataBlock();
        }

        public LandStatRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RequestData.FromBytes(bytes, ref i);
        }

        public LandStatRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RequestData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += RequestData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RequestData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LandStatReplyPacket : Packet
    {
        /// <exclude/>
        public sealed class RequestDataBlock : PacketBlock
        {
            public uint ReportType;
            public uint RequestFlags;
            public uint TotalObjectCount;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public RequestDataBlock() { }
            public RequestDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ReportType = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RequestFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TotalObjectCount = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ReportType, bytes, i); i += 4;
                Utils.UIntToBytes(RequestFlags, bytes, i); i += 4;
                Utils.UIntToBytes(TotalObjectCount, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class ReportDataBlock : PacketBlock
        {
            public uint TaskLocalID;
            public UUID TaskID;
            public float LocationX;
            public float LocationY;
            public float LocationZ;
            public float Score;
            public byte[] TaskName;
            public byte[] OwnerName;

            public override int Length
            {
                get
                {
                    int length = 38;
                    if (TaskName != null) { length += TaskName.Length; }
                    if (OwnerName != null) { length += OwnerName.Length; }
                    return length;
                }
            }

            public ReportDataBlock() { }
            public ReportDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TaskLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TaskID.FromBytes(bytes, i); i += 16;
                    LocationX = Utils.BytesToFloat(bytes, i); i += 4;
                    LocationY = Utils.BytesToFloat(bytes, i); i += 4;
                    LocationZ = Utils.BytesToFloat(bytes, i); i += 4;
                    Score = Utils.BytesToFloat(bytes, i); i += 4;
                    length = bytes[i++];
                    TaskName = new byte[length];
                    Buffer.BlockCopy(bytes, i, TaskName, 0, length); i += length;
                    length = bytes[i++];
                    OwnerName = new byte[length];
                    Buffer.BlockCopy(bytes, i, OwnerName, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(TaskLocalID, bytes, i); i += 4;
                TaskID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(LocationX, bytes, i); i += 4;
                Utils.FloatToBytes(LocationY, bytes, i); i += 4;
                Utils.FloatToBytes(LocationZ, bytes, i); i += 4;
                Utils.FloatToBytes(Score, bytes, i); i += 4;
                bytes[i++] = (byte)TaskName.Length;
                Buffer.BlockCopy(TaskName, 0, bytes, i, TaskName.Length); i += TaskName.Length;
                bytes[i++] = (byte)OwnerName.Length;
                Buffer.BlockCopy(OwnerName, 0, bytes, i, OwnerName.Length); i += OwnerName.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += RequestData.Length;
                for (int j = 0; j < ReportData.Length; j++)
                    length += ReportData[j].Length;
                return length;
            }
        }
        public RequestDataBlock RequestData;
        public ReportDataBlock[] ReportData;

        public LandStatReplyPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.LandStatReply;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 422;
            Header.Reliable = true;
            RequestData = new RequestDataBlock();
            ReportData = null;
        }

        public LandStatReplyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RequestData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ReportData == null || ReportData.Length != -1) {
                ReportData = new ReportDataBlock[count];
                for(int j = 0; j < count; j++)
                { ReportData[j] = new ReportDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ReportData[j].FromBytes(bytes, ref i); }
        }

        public LandStatReplyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RequestData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ReportData == null || ReportData.Length != count) {
                ReportData = new ReportDataBlock[count];
                for(int j = 0; j < count; j++)
                { ReportData[j] = new ReportDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ReportData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += RequestData.Length;
            length++;
            for (int j = 0; j < ReportData.Length; j++) { length += ReportData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RequestData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ReportData.Length;
            for (int j = 0; j < ReportData.Length; j++) { ReportData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += RequestData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            RequestData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ReportDataStart = 0;
            do
            {
                int variableLength = 0;
                int ReportDataCount = 0;

                i = ReportDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ReportData.Length) {
                    int blockLength = ReportData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ReportDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ReportDataCount;
                for (i = ReportDataStart; i < ReportDataStart + ReportDataCount; i++) { ReportData[i].ToBytes(packet, ref length); }
                ReportDataStart += ReportDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ReportDataStart < ReportData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ErrorPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class DataBlock : PacketBlock
        {
            public int Code;
            public byte[] Token;
            public UUID ID;
            public byte[] System;
            public byte[] Message;
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 26;
                    if (Token != null) { length += Token.Length; }
                    if (System != null) { length += System.Length; }
                    if (Message != null) { length += Message.Length; }
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public DataBlock() { }
            public DataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    Code = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Token = new byte[length];
                    Buffer.BlockCopy(bytes, i, Token, 0, length); i += length;
                    ID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    System = new byte[length];
                    Buffer.BlockCopy(bytes, i, System, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Message = new byte[length];
                    Buffer.BlockCopy(bytes, i, Message, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(Code, bytes, i); i += 4;
                bytes[i++] = (byte)Token.Length;
                Buffer.BlockCopy(Token, 0, bytes, i, Token.Length); i += Token.Length;
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)System.Length;
                Buffer.BlockCopy(System, 0, bytes, i, System.Length); i += System.Length;
                bytes[i++] = (byte)(Message.Length % 256);
                bytes[i++] = (byte)((Message.Length >> 8) % 256);
                Buffer.BlockCopy(Message, 0, bytes, i, Message.Length); i += Message.Length;
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += Data.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public DataBlock Data;

        public ErrorPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.Error;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 423;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Data = new DataBlock();
        }

        public ErrorPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public ErrorPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            Data.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += Data.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            Data.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectIncludeInSearchPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public bool IncludeInSearch;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    IncludeInSearch = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = (byte)((IncludeInSearch) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectIncludeInSearchPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectIncludeInSearch;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 424;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectIncludeInSearchPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectIncludeInSearchPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RezRestoreToWorldPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryDataBlock : PacketBlock
        {
            public UUID ItemID;
            public UUID FolderID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public bool GroupOwned;
            public UUID TransactionID;
            public sbyte Type;
            public sbyte InvType;
            public uint Flags;
            public byte SaleType;
            public int SalePrice;
            public byte[] Name;
            public byte[] Description;
            public int CreationDate;
            public uint CRC;

            public override int Length
            {
                get
                {
                    int length = 138;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryDataBlock() { }
            public InventoryDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    CreationDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                bytes[i++] = (byte)((GroupOwned) ? 1 : 0);
                TransactionID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                Utils.IntToBytes(CreationDate, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryDataBlock InventoryData;

        public RezRestoreToWorldPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RezRestoreToWorld;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 425;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            InventoryData = new InventoryDataBlock();
        }

        public RezRestoreToWorldPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public RezRestoreToWorldPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LinkInventoryItemPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class InventoryBlockBlock : PacketBlock
        {
            public uint CallbackID;
            public UUID FolderID;
            public UUID TransactionID;
            public UUID OldItemID;
            public sbyte Type;
            public sbyte InvType;
            public byte[] Name;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 56;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public InventoryBlockBlock() { }
            public InventoryBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    CallbackID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    FolderID.FromBytes(bytes, i); i += 16;
                    TransactionID.FromBytes(bytes, i); i += 16;
                    OldItemID.FromBytes(bytes, i); i += 16;
                    Type = (sbyte)bytes[i++];
                    InvType = (sbyte)bytes[i++];
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(CallbackID, bytes, i); i += 4;
                FolderID.ToBytes(bytes, i); i += 16;
                TransactionID.ToBytes(bytes, i); i += 16;
                OldItemID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Type;
                bytes[i++] = (byte)InvType;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += AgentData.Length;
                length += InventoryBlock.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public InventoryBlockBlock InventoryBlock;

        public LinkInventoryItemPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LinkInventoryItem;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 426;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            InventoryBlock = new InventoryBlockBlock();
        }

        public LinkInventoryItemPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public LinkInventoryItemPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            InventoryBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += AgentData.Length;
            length += InventoryBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            InventoryBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PacketAckPacket : Packet
    {
        /// <exclude/>
        public sealed class PacketsBlock : PacketBlock
        {
            public uint ID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public PacketsBlock() { }
            public PacketsBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 11;
                for (int j = 0; j < Packets.Length; j++)
                    length += Packets[j].Length;
                return length;
            }
        }
        public PacketsBlock[] Packets;

        public PacketAckPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.PacketAck;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 65531;
            Header.Reliable = true;
            Packets = null;
        }

        public PacketAckPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(Packets == null || Packets.Length != -1) {
                Packets = new PacketsBlock[count];
                for(int j = 0; j < count; j++)
                { Packets[j] = new PacketsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Packets[j].FromBytes(bytes, ref i); }
        }

        public PacketAckPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(Packets == null || Packets.Length != count) {
                Packets = new PacketsBlock[count];
                for(int j = 0; j < count; j++)
                { Packets[j] = new PacketsBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Packets[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length++;
            for (int j = 0; j < Packets.Length; j++) { length += Packets[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Packets.Length;
            for (int j = 0; j < Packets.Length; j++) { Packets[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 10;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int PacketsStart = 0;
            do
            {
                int variableLength = 0;
                int PacketsCount = 0;

                i = PacketsStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Packets.Length) {
                    int blockLength = Packets[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++PacketsCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)PacketsCount;
                for (i = PacketsStart; i < PacketsStart + PacketsCount; i++) { Packets[i].ToBytes(packet, ref length); }
                PacketsStart += PacketsCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                PacketsStart < Packets.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class OpenCircuitPacket : Packet
    {
        /// <exclude/>
        public sealed class CircuitInfoBlock : PacketBlock
        {
            public uint IP;
            public ushort Port;

            public override int Length
            {
                get
                {
                    return 6;
                }
            }

            public CircuitInfoBlock() { }
            public CircuitInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    IP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Port = (ushort)((bytes[i++] << 8) + bytes[i++]);
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(IP, bytes, i); i += 4;
                bytes[i++] = (byte)((Port >> 8) % 256);
                bytes[i++] = (byte)(Port % 256);
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += CircuitInfo.Length;
                return length;
            }
        }
        public CircuitInfoBlock CircuitInfo;

        public OpenCircuitPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.OpenCircuit;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 65532;
            Header.Reliable = true;
            CircuitInfo = new CircuitInfoBlock();
        }

        public OpenCircuitPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            CircuitInfo.FromBytes(bytes, ref i);
        }

        public OpenCircuitPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            CircuitInfo.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            length += CircuitInfo.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            CircuitInfo.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CloseCircuitPacket : Packet
    {
        public override int Length
        {
            get
            {
                int length = 10;
                return length;
            }
        }

        public CloseCircuitPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CloseCircuit;
            Header = new Header();
            Header.Frequency = PacketFrequency.Low;
            Header.ID = 65533;
            Header.Reliable = true;
        }

        public CloseCircuitPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
        }

        public CloseCircuitPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
        }

        public override byte[] ToBytes()
        {
            int length = 10;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectAddPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public UUID GroupID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public byte PCode;
            public byte Material;
            public uint AddFlags;
            public byte PathCurve;
            public byte ProfileCurve;
            public ushort PathBegin;
            public ushort PathEnd;
            public byte PathScaleX;
            public byte PathScaleY;
            public byte PathShearX;
            public byte PathShearY;
            public sbyte PathTwist;
            public sbyte PathTwistBegin;
            public sbyte PathRadiusOffset;
            public sbyte PathTaperX;
            public sbyte PathTaperY;
            public byte PathRevolutions;
            public sbyte PathSkew;
            public ushort ProfileBegin;
            public ushort ProfileEnd;
            public ushort ProfileHollow;
            public byte BypassRaycast;
            public Vector3 RayStart;
            public Vector3 RayEnd;
            public UUID RayTargetID;
            public byte RayEndIsIntersection;
            public Vector3 Scale;
            public Quaternion Rotation;
            public byte State;

            public override int Length
            {
                get
                {
                    return 96;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PCode = (byte)bytes[i++];
                    Material = (byte)bytes[i++];
                    AddFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PathCurve = (byte)bytes[i++];
                    ProfileCurve = (byte)bytes[i++];
                    PathBegin = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    PathEnd = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    PathScaleX = (byte)bytes[i++];
                    PathScaleY = (byte)bytes[i++];
                    PathShearX = (byte)bytes[i++];
                    PathShearY = (byte)bytes[i++];
                    PathTwist = (sbyte)bytes[i++];
                    PathTwistBegin = (sbyte)bytes[i++];
                    PathRadiusOffset = (sbyte)bytes[i++];
                    PathTaperX = (sbyte)bytes[i++];
                    PathTaperY = (sbyte)bytes[i++];
                    PathRevolutions = (byte)bytes[i++];
                    PathSkew = (sbyte)bytes[i++];
                    ProfileBegin = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ProfileEnd = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ProfileHollow = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    BypassRaycast = (byte)bytes[i++];
                    RayStart.FromBytes(bytes, i); i += 12;
                    RayEnd.FromBytes(bytes, i); i += 12;
                    RayTargetID.FromBytes(bytes, i); i += 16;
                    RayEndIsIntersection = (byte)bytes[i++];
                    Scale.FromBytes(bytes, i); i += 12;
                    Rotation.FromBytes(bytes, i, true); i += 12;
                    State = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = PCode;
                bytes[i++] = Material;
                Utils.UIntToBytes(AddFlags, bytes, i); i += 4;
                bytes[i++] = PathCurve;
                bytes[i++] = ProfileCurve;
                bytes[i++] = (byte)(PathBegin % 256);
                bytes[i++] = (byte)((PathBegin >> 8) % 256);
                bytes[i++] = (byte)(PathEnd % 256);
                bytes[i++] = (byte)((PathEnd >> 8) % 256);
                bytes[i++] = PathScaleX;
                bytes[i++] = PathScaleY;
                bytes[i++] = PathShearX;
                bytes[i++] = PathShearY;
                bytes[i++] = (byte)PathTwist;
                bytes[i++] = (byte)PathTwistBegin;
                bytes[i++] = (byte)PathRadiusOffset;
                bytes[i++] = (byte)PathTaperX;
                bytes[i++] = (byte)PathTaperY;
                bytes[i++] = PathRevolutions;
                bytes[i++] = (byte)PathSkew;
                bytes[i++] = (byte)(ProfileBegin % 256);
                bytes[i++] = (byte)((ProfileBegin >> 8) % 256);
                bytes[i++] = (byte)(ProfileEnd % 256);
                bytes[i++] = (byte)((ProfileEnd >> 8) % 256);
                bytes[i++] = (byte)(ProfileHollow % 256);
                bytes[i++] = (byte)((ProfileHollow >> 8) % 256);
                bytes[i++] = BypassRaycast;
                RayStart.ToBytes(bytes, i); i += 12;
                RayEnd.ToBytes(bytes, i); i += 12;
                RayTargetID.ToBytes(bytes, i); i += 16;
                bytes[i++] = RayEndIsIntersection;
                Scale.ToBytes(bytes, i); i += 12;
                Rotation.ToBytes(bytes, i); i += 12;
                bytes[i++] = State;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += AgentData.Length;
                length += ObjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;

        public ObjectAddPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ObjectAdd;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 1;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
        }

        public ObjectAddPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public ObjectAddPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class MultipleObjectUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public byte Type;
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 6;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Type = (byte)bytes[i++];
                    length = bytes[i++];
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                bytes[i++] = Type;
                bytes[i++] = (byte)Data.Length;
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public MultipleObjectUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.MultipleObjectUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 2;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public MultipleObjectUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public MultipleObjectUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 8;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RequestMultipleObjectsPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public byte CacheMissType;
            public uint ID;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    CacheMissType = (byte)bytes[i++];
                    ID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = CacheMissType;
                Utils.UIntToBytes(ID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public RequestMultipleObjectsPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RequestMultipleObjects;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 3;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public RequestMultipleObjectsPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public RequestMultipleObjectsPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 8;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectPositionPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ObjectLocalID;
            public Vector3 Position;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectLocalID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Position.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ObjectLocalID, bytes, i); i += 4;
                Position.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                length += AgentData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock[] ObjectData;

        public ObjectPositionPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectPosition;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 4;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = null;
        }

        public ObjectPositionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectPositionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 8;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class RequestObjectPropertiesFamilyPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint RequestFlags;
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RequestFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(RequestFlags, bytes, i); i += 4;
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += AgentData.Length;
                length += ObjectData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ObjectDataBlock ObjectData;

        public RequestObjectPropertiesFamilyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.RequestObjectPropertiesFamily;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 5;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ObjectData = new ObjectDataBlock();
        }

        public RequestObjectPropertiesFamilyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public RequestObjectPropertiesFamilyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CoarseLocationUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class LocationBlock : PacketBlock
        {
            public byte X;
            public byte Y;
            public byte Z;

            public override int Length
            {
                get
                {
                    return 3;
                }
            }

            public LocationBlock() { }
            public LocationBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    X = (byte)bytes[i++];
                    Y = (byte)bytes[i++];
                    Z = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = X;
                bytes[i++] = Y;
                bytes[i++] = Z;
            }

        }

        /// <exclude/>
        public sealed class IndexBlock : PacketBlock
        {
            public short You;
            public short Prey;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public IndexBlock() { }
            public IndexBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    You = (short)(bytes[i++] + (bytes[i++] << 8));
                    Prey = (short)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(You % 256);
                bytes[i++] = (byte)((You >> 8) % 256);
                bytes[i++] = (byte)(Prey % 256);
                bytes[i++] = (byte)((Prey >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                for (int j = 0; j < Location.Length; j++)
                    length += Location[j].Length;
                length += Index.Length;
                for (int j = 0; j < AgentData.Length; j++)
                    length += AgentData[j].Length;
                return length;
            }
        }
        public LocationBlock[] Location;
        public IndexBlock Index;
        public AgentDataBlock[] AgentData;

        public CoarseLocationUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.CoarseLocationUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 6;
            Header.Reliable = true;
            Location = null;
            Index = new IndexBlock();
            AgentData = null;
        }

        public CoarseLocationUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(Location == null || Location.Length != -1) {
                Location = new LocationBlock[count];
                for(int j = 0; j < count; j++)
                { Location[j] = new LocationBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Location[j].FromBytes(bytes, ref i); }
            Index.FromBytes(bytes, ref i);
            count = (int)bytes[i++];
            if(AgentData == null || AgentData.Length != -1) {
                AgentData = new AgentDataBlock[count];
                for(int j = 0; j < count; j++)
                { AgentData[j] = new AgentDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentData[j].FromBytes(bytes, ref i); }
        }

        public CoarseLocationUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(Location == null || Location.Length != count) {
                Location = new LocationBlock[count];
                for(int j = 0; j < count; j++)
                { Location[j] = new LocationBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Location[j].FromBytes(bytes, ref i); }
            Index.FromBytes(bytes, ref i);
            count = (int)bytes[i++];
            if(AgentData == null || AgentData.Length != count) {
                AgentData = new AgentDataBlock[count];
                for(int j = 0; j < count; j++)
                { AgentData[j] = new AgentDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += Index.Length;
            length++;
            for (int j = 0; j < Location.Length; j++) { length += Location[j].Length; }
            length++;
            for (int j = 0; j < AgentData.Length; j++) { length += AgentData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Location.Length;
            for (int j = 0; j < Location.Length; j++) { Location[j].ToBytes(bytes, ref i); }
            Index.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AgentData.Length;
            for (int j = 0; j < AgentData.Length; j++) { AgentData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CrossedRegionPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RegionDataBlock : PacketBlock
        {
            public uint SimIP;
            public ushort SimPort;
            public ulong RegionHandle;
            public byte[] SeedCapability;

            public override int Length
            {
                get
                {
                    int length = 16;
                    if (SeedCapability != null) { length += SeedCapability.Length; }
                    return length;
                }
            }

            public RegionDataBlock() { }
            public RegionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    SimIP = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SimPort = (ushort)((bytes[i++] << 8) + bytes[i++]);
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    SeedCapability = new byte[length];
                    Buffer.BlockCopy(bytes, i, SeedCapability, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(SimIP, bytes, i); i += 4;
                bytes[i++] = (byte)((SimPort >> 8) % 256);
                bytes[i++] = (byte)(SimPort % 256);
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = (byte)(SeedCapability.Length % 256);
                bytes[i++] = (byte)((SeedCapability.Length >> 8) % 256);
                Buffer.BlockCopy(SeedCapability, 0, bytes, i, SeedCapability.Length); i += SeedCapability.Length;
            }

        }

        /// <exclude/>
        public sealed class InfoBlock : PacketBlock
        {
            public Vector3 Position;
            public Vector3 LookAt;

            public override int Length
            {
                get
                {
                    return 24;
                }
            }

            public InfoBlock() { }
            public InfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Position.FromBytes(bytes, i); i += 12;
                    LookAt.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Position.ToBytes(bytes, i); i += 12;
                LookAt.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += AgentData.Length;
                length += RegionData.Length;
                length += Info.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RegionDataBlock RegionData;
        public InfoBlock Info;

        public CrossedRegionPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CrossedRegion;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 7;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RegionData = new RegionDataBlock();
            Info = new InfoBlock();
        }

        public CrossedRegionPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            RegionData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public CrossedRegionPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            RegionData.FromBytes(bytes, ref i);
            Info.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length += RegionData.Length;
            length += Info.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            RegionData.ToBytes(bytes, ref i);
            Info.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ConfirmEnableSimulatorPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ConfirmEnableSimulatorPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ConfirmEnableSimulator;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 8;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public ConfirmEnableSimulatorPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ConfirmEnableSimulatorPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectPropertiesPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID CreatorID;
            public UUID OwnerID;
            public UUID GroupID;
            public ulong CreationDate;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public int OwnershipCost;
            public byte SaleType;
            public int SalePrice;
            public byte AggregatePerms;
            public byte AggregatePermTextures;
            public byte AggregatePermTexturesOwner;
            public uint Category;
            public short InventorySerial;
            public UUID ItemID;
            public UUID FolderID;
            public UUID FromTaskID;
            public UUID LastOwnerID;
            public byte[] Name;
            public byte[] Description;
            public byte[] TouchName;
            public byte[] SitName;
            public byte[] TextureID;

            public override int Length
            {
                get
                {
                    int length = 179;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    if (TouchName != null) { length += TouchName.Length; }
                    if (SitName != null) { length += SitName.Length; }
                    if (TextureID != null) { length += TextureID.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    CreatorID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    CreationDate = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnershipCost = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AggregatePerms = (byte)bytes[i++];
                    AggregatePermTextures = (byte)bytes[i++];
                    AggregatePermTexturesOwner = (byte)bytes[i++];
                    Category = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    InventorySerial = (short)(bytes[i++] + (bytes[i++] << 8));
                    ItemID.FromBytes(bytes, i); i += 16;
                    FolderID.FromBytes(bytes, i); i += 16;
                    FromTaskID.FromBytes(bytes, i); i += 16;
                    LastOwnerID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                    length = bytes[i++];
                    TouchName = new byte[length];
                    Buffer.BlockCopy(bytes, i, TouchName, 0, length); i += length;
                    length = bytes[i++];
                    SitName = new byte[length];
                    Buffer.BlockCopy(bytes, i, SitName, 0, length); i += length;
                    length = bytes[i++];
                    TextureID = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureID, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                CreatorID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(CreationDate, bytes, i); i += 8;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                Utils.IntToBytes(OwnershipCost, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = AggregatePerms;
                bytes[i++] = AggregatePermTextures;
                bytes[i++] = AggregatePermTexturesOwner;
                Utils.UIntToBytes(Category, bytes, i); i += 4;
                bytes[i++] = (byte)(InventorySerial % 256);
                bytes[i++] = (byte)((InventorySerial >> 8) % 256);
                ItemID.ToBytes(bytes, i); i += 16;
                FolderID.ToBytes(bytes, i); i += 16;
                FromTaskID.ToBytes(bytes, i); i += 16;
                LastOwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
                bytes[i++] = (byte)TouchName.Length;
                Buffer.BlockCopy(TouchName, 0, bytes, i, TouchName.Length); i += TouchName.Length;
                bytes[i++] = (byte)SitName.Length;
                Buffer.BlockCopy(SitName, 0, bytes, i, SitName.Length); i += SitName.Length;
                bytes[i++] = (byte)TextureID.Length;
                Buffer.BlockCopy(TextureID, 0, bytes, i, TextureID.Length); i += TextureID.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public ObjectDataBlock[] ObjectData;

        public ObjectPropertiesPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectProperties;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 9;
            Header.Reliable = true;
            Header.Zerocoded = true;
            ObjectData = null;
        }

        public ObjectPropertiesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectPropertiesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 8;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectPropertiesFamilyPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint RequestFlags;
            public UUID ObjectID;
            public UUID OwnerID;
            public UUID GroupID;
            public uint BaseMask;
            public uint OwnerMask;
            public uint GroupMask;
            public uint EveryoneMask;
            public uint NextOwnerMask;
            public int OwnershipCost;
            public byte SaleType;
            public int SalePrice;
            public uint Category;
            public UUID LastOwnerID;
            public byte[] Name;
            public byte[] Description;

            public override int Length
            {
                get
                {
                    int length = 103;
                    if (Name != null) { length += Name.Length; }
                    if (Description != null) { length += Description.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RequestFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ObjectID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    GroupID.FromBytes(bytes, i); i += 16;
                    BaseMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EveryoneMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    NextOwnerMask = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnershipCost = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SaleType = (byte)bytes[i++];
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Category = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LastOwnerID.FromBytes(bytes, i); i += 16;
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Description = new byte[length];
                    Buffer.BlockCopy(bytes, i, Description, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(RequestFlags, bytes, i); i += 4;
                ObjectID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(BaseMask, bytes, i); i += 4;
                Utils.UIntToBytes(OwnerMask, bytes, i); i += 4;
                Utils.UIntToBytes(GroupMask, bytes, i); i += 4;
                Utils.UIntToBytes(EveryoneMask, bytes, i); i += 4;
                Utils.UIntToBytes(NextOwnerMask, bytes, i); i += 4;
                Utils.IntToBytes(OwnershipCost, bytes, i); i += 4;
                bytes[i++] = SaleType;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                Utils.UIntToBytes(Category, bytes, i); i += 4;
                LastOwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Description.Length;
                Buffer.BlockCopy(Description, 0, bytes, i, Description.Length); i += Description.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += ObjectData.Length;
                return length;
            }
        }
        public ObjectDataBlock ObjectData;

        public ObjectPropertiesFamilyPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ObjectPropertiesFamily;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 10;
            Header.Reliable = true;
            Header.Zerocoded = true;
            ObjectData = new ObjectDataBlock();
        }

        public ObjectPropertiesFamilyPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ObjectData.FromBytes(bytes, ref i);
        }

        public ObjectPropertiesFamilyPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ObjectData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += ObjectData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ObjectData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelPropertiesRequestPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int SequenceID;
            public float West;
            public float South;
            public float East;
            public float North;
            public bool SnapSelection;

            public override int Length
            {
                get
                {
                    return 21;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    West = Utils.BytesToFloat(bytes, i); i += 4;
                    South = Utils.BytesToFloat(bytes, i); i += 4;
                    East = Utils.BytesToFloat(bytes, i); i += 4;
                    North = Utils.BytesToFloat(bytes, i); i += 4;
                    SnapSelection = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                Utils.FloatToBytes(West, bytes, i); i += 4;
                Utils.FloatToBytes(South, bytes, i); i += 4;
                Utils.FloatToBytes(East, bytes, i); i += 4;
                Utils.FloatToBytes(North, bytes, i); i += 4;
                bytes[i++] = (byte)((SnapSelection) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += AgentData.Length;
                length += ParcelData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public ParcelDataBlock ParcelData;

        public ParcelPropertiesRequestPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelPropertiesRequest;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 11;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            ParcelData = new ParcelDataBlock();
        }

        public ParcelPropertiesRequestPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public ParcelPropertiesRequestPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            ParcelData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length += ParcelData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AttachedSoundPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlockBlock : PacketBlock
        {
            public UUID SoundID;
            public UUID ObjectID;
            public UUID OwnerID;
            public float Gain;
            public byte Flags;

            public override int Length
            {
                get
                {
                    return 53;
                }
            }

            public DataBlockBlock() { }
            public DataBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SoundID.FromBytes(bytes, i); i += 16;
                    ObjectID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    Gain = Utils.BytesToFloat(bytes, i); i += 4;
                    Flags = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                SoundID.ToBytes(bytes, i); i += 16;
                ObjectID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(Gain, bytes, i); i += 4;
                bytes[i++] = Flags;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += DataBlock.Length;
                return length;
            }
        }
        public DataBlockBlock DataBlock;

        public AttachedSoundPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AttachedSound;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 13;
            Header.Reliable = true;
            DataBlock = new DataBlockBlock();
        }

        public AttachedSoundPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            DataBlock.FromBytes(bytes, ref i);
        }

        public AttachedSoundPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            DataBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += DataBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            DataBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AttachedSoundGainChangePacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlockBlock : PacketBlock
        {
            public UUID ObjectID;
            public float Gain;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public DataBlockBlock() { }
            public DataBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    Gain = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(Gain, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += DataBlock.Length;
                return length;
            }
        }
        public DataBlockBlock DataBlock;

        public AttachedSoundGainChangePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AttachedSoundGainChange;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 14;
            Header.Reliable = true;
            DataBlock = new DataBlockBlock();
        }

        public AttachedSoundGainChangePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            DataBlock.FromBytes(bytes, ref i);
        }

        public AttachedSoundGainChangePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            DataBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += DataBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            DataBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class PreloadSoundPacket : Packet
    {
        /// <exclude/>
        public sealed class DataBlockBlock : PacketBlock
        {
            public UUID ObjectID;
            public UUID OwnerID;
            public UUID SoundID;

            public override int Length
            {
                get
                {
                    return 48;
                }
            }

            public DataBlockBlock() { }
            public DataBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    SoundID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                SoundID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                for (int j = 0; j < DataBlock.Length; j++)
                    length += DataBlock[j].Length;
                return length;
            }
        }
        public DataBlockBlock[] DataBlock;

        public PreloadSoundPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.PreloadSound;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 15;
            Header.Reliable = true;
            DataBlock = null;
        }

        public PreloadSoundPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(DataBlock == null || DataBlock.Length != -1) {
                DataBlock = new DataBlockBlock[count];
                for(int j = 0; j < count; j++)
                { DataBlock[j] = new DataBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { DataBlock[j].FromBytes(bytes, ref i); }
        }

        public PreloadSoundPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(DataBlock == null || DataBlock.Length != count) {
                DataBlock = new DataBlockBlock[count];
                for(int j = 0; j < count; j++)
                { DataBlock[j] = new DataBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { DataBlock[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length++;
            for (int j = 0; j < DataBlock.Length; j++) { length += DataBlock[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)DataBlock.Length;
            for (int j = 0; j < DataBlock.Length; j++) { DataBlock[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 8;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int DataBlockStart = 0;
            do
            {
                int variableLength = 0;
                int DataBlockCount = 0;

                i = DataBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < DataBlock.Length) {
                    int blockLength = DataBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++DataBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)DataBlockCount;
                for (i = DataBlockStart; i < DataBlockStart + DataBlockCount; i++) { DataBlock[i].ToBytes(packet, ref length); }
                DataBlockStart += DataBlockCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                DataBlockStart < DataBlock.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ViewerEffectPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class EffectBlock : PacketBlock
        {
            public UUID ID;
            public UUID AgentID;
            public byte Type;
            public float Duration;
            public byte[] Color;
            public byte[] TypeData;

            public override int Length
            {
                get
                {
                    int length = 42;
                    if (TypeData != null) { length += TypeData.Length; }
                    return length;
                }
            }

            public EffectBlock() { }
            public EffectBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    AgentID.FromBytes(bytes, i); i += 16;
                    Type = (byte)bytes[i++];
                    Duration = Utils.BytesToFloat(bytes, i); i += 4;
                    Color = new byte[4];
                    Buffer.BlockCopy(bytes, i, Color, 0, 4); i += 4;
                    length = bytes[i++];
                    TypeData = new byte[length];
                    Buffer.BlockCopy(bytes, i, TypeData, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                AgentID.ToBytes(bytes, i); i += 16;
                bytes[i++] = Type;
                Utils.FloatToBytes(Duration, bytes, i); i += 4;
                Buffer.BlockCopy(Color, 0, bytes, i, 4);i += 4;
                bytes[i++] = (byte)TypeData.Length;
                Buffer.BlockCopy(TypeData, 0, bytes, i, TypeData.Length); i += TypeData.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                length += AgentData.Length;
                for (int j = 0; j < Effect.Length; j++)
                    length += Effect[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public EffectBlock[] Effect;

        public ViewerEffectPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ViewerEffect;
            Header = new Header();
            Header.Frequency = PacketFrequency.Medium;
            Header.ID = 17;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            Effect = null;
        }

        public ViewerEffectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Effect == null || Effect.Length != -1) {
                Effect = new EffectBlock[count];
                for(int j = 0; j < count; j++)
                { Effect[j] = new EffectBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Effect[j].FromBytes(bytes, ref i); }
        }

        public ViewerEffectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(Effect == null || Effect.Length != count) {
                Effect = new EffectBlock[count];
                for(int j = 0; j < count; j++)
                { Effect[j] = new EffectBlock(); }
            }
            for (int j = 0; j < count; j++)
            { Effect[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 8;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < Effect.Length; j++) { length += Effect[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)Effect.Length;
            for (int j = 0; j < Effect.Length; j++) { Effect[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 8;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int EffectStart = 0;
            do
            {
                int variableLength = 0;
                int EffectCount = 0;

                i = EffectStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < Effect.Length) {
                    int blockLength = Effect[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++EffectCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)EffectCount;
                for (i = EffectStart; i < EffectStart + EffectCount; i++) { Effect[i].ToBytes(packet, ref length); }
                EffectStart += EffectCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                EffectStart < Effect.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class StartPingCheckPacket : Packet
    {
        /// <exclude/>
        public sealed class PingIDBlock : PacketBlock
        {
            public byte PingID;
            public uint OldestUnacked;

            public override int Length
            {
                get
                {
                    return 5;
                }
            }

            public PingIDBlock() { }
            public PingIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PingID = (byte)bytes[i++];
                    OldestUnacked = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = PingID;
                Utils.UIntToBytes(OldestUnacked, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += PingID.Length;
                return length;
            }
        }
        public PingIDBlock PingID;

        public StartPingCheckPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.StartPingCheck;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 1;
            Header.Reliable = true;
            PingID = new PingIDBlock();
        }

        public StartPingCheckPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            PingID.FromBytes(bytes, ref i);
        }

        public StartPingCheckPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            PingID.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += PingID.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            PingID.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CompletePingCheckPacket : Packet
    {
        /// <exclude/>
        public sealed class PingIDBlock : PacketBlock
        {
            public byte PingID;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public PingIDBlock() { }
            public PingIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    PingID = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = PingID;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += PingID.Length;
                return length;
            }
        }
        public PingIDBlock PingID;

        public CompletePingCheckPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CompletePingCheck;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 2;
            Header.Reliable = true;
            PingID = new PingIDBlock();
        }

        public CompletePingCheckPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            PingID.FromBytes(bytes, ref i);
        }

        public CompletePingCheckPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            PingID.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += PingID.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            PingID.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;
            public Quaternion BodyRotation;
            public Quaternion HeadRotation;
            public byte State;
            public Vector3 CameraCenter;
            public Vector3 CameraAtAxis;
            public Vector3 CameraLeftAxis;
            public Vector3 CameraUpAxis;
            public float Far;
            public uint ControlFlags;
            public byte Flags;

            public override int Length
            {
                get
                {
                    return 114;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    BodyRotation.FromBytes(bytes, i, true); i += 12;
                    HeadRotation.FromBytes(bytes, i, true); i += 12;
                    State = (byte)bytes[i++];
                    CameraCenter.FromBytes(bytes, i); i += 12;
                    CameraAtAxis.FromBytes(bytes, i); i += 12;
                    CameraLeftAxis.FromBytes(bytes, i); i += 12;
                    CameraUpAxis.FromBytes(bytes, i); i += 12;
                    Far = Utils.BytesToFloat(bytes, i); i += 4;
                    ControlFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Flags = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                BodyRotation.ToBytes(bytes, i); i += 12;
                HeadRotation.ToBytes(bytes, i); i += 12;
                bytes[i++] = State;
                CameraCenter.ToBytes(bytes, i); i += 12;
                CameraAtAxis.ToBytes(bytes, i); i += 12;
                CameraLeftAxis.ToBytes(bytes, i); i += 12;
                CameraUpAxis.ToBytes(bytes, i); i += 12;
                Utils.FloatToBytes(Far, bytes, i); i += 4;
                Utils.UIntToBytes(ControlFlags, bytes, i); i += 4;
                bytes[i++] = Flags;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 4;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
        }

        public AgentUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentAnimationPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class AnimationListBlock : PacketBlock
        {
            public UUID AnimID;
            public bool StartAnim;

            public override int Length
            {
                get
                {
                    return 17;
                }
            }

            public AnimationListBlock() { }
            public AnimationListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AnimID.FromBytes(bytes, i); i += 16;
                    StartAnim = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AnimID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((StartAnim) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class PhysicalAvatarEventListBlock : PacketBlock
        {
            public byte[] TypeData;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (TypeData != null) { length += TypeData.Length; }
                    return length;
                }
            }

            public PhysicalAvatarEventListBlock() { }
            public PhysicalAvatarEventListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    TypeData = new byte[length];
                    Buffer.BlockCopy(bytes, i, TypeData, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)TypeData.Length;
                Buffer.BlockCopy(TypeData, 0, bytes, i, TypeData.Length); i += TypeData.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 9;
                length += AgentData.Length;
                for (int j = 0; j < AnimationList.Length; j++)
                    length += AnimationList[j].Length;
                for (int j = 0; j < PhysicalAvatarEventList.Length; j++)
                    length += PhysicalAvatarEventList[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public AnimationListBlock[] AnimationList;
        public PhysicalAvatarEventListBlock[] PhysicalAvatarEventList;

        public AgentAnimationPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AgentAnimation;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 5;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            AnimationList = null;
            PhysicalAvatarEventList = null;
        }

        public AgentAnimationPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AnimationList == null || AnimationList.Length != -1) {
                AnimationList = new AnimationListBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationList[j] = new AnimationListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationList[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(PhysicalAvatarEventList == null || PhysicalAvatarEventList.Length != -1) {
                PhysicalAvatarEventList = new PhysicalAvatarEventListBlock[count];
                for(int j = 0; j < count; j++)
                { PhysicalAvatarEventList[j] = new PhysicalAvatarEventListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { PhysicalAvatarEventList[j].FromBytes(bytes, ref i); }
        }

        public AgentAnimationPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AnimationList == null || AnimationList.Length != count) {
                AnimationList = new AnimationListBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationList[j] = new AnimationListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationList[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(PhysicalAvatarEventList == null || PhysicalAvatarEventList.Length != count) {
                PhysicalAvatarEventList = new PhysicalAvatarEventListBlock[count];
                for(int j = 0; j < count; j++)
                { PhysicalAvatarEventList[j] = new PhysicalAvatarEventListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { PhysicalAvatarEventList[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < AnimationList.Length; j++) { length += AnimationList[j].Length; }
            length++;
            for (int j = 0; j < PhysicalAvatarEventList.Length; j++) { length += PhysicalAvatarEventList[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AnimationList.Length;
            for (int j = 0; j < AnimationList.Length; j++) { AnimationList[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)PhysicalAvatarEventList.Length;
            for (int j = 0; j < PhysicalAvatarEventList.Length; j++) { PhysicalAvatarEventList[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 2;

            int AnimationListStart = 0;
            int PhysicalAvatarEventListStart = 0;
            do
            {
                int variableLength = 0;
                int AnimationListCount = 0;
                int PhysicalAvatarEventListCount = 0;

                i = AnimationListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AnimationList.Length) {
                    int blockLength = AnimationList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AnimationListCount;
                    }
                    else { break; }
                    ++i;
                }

                i = PhysicalAvatarEventListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < PhysicalAvatarEventList.Length) {
                    int blockLength = PhysicalAvatarEventList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++PhysicalAvatarEventListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AnimationListCount;
                for (i = AnimationListStart; i < AnimationListStart + AnimationListCount; i++) { AnimationList[i].ToBytes(packet, ref length); }
                AnimationListStart += AnimationListCount;

                packet[length++] = (byte)PhysicalAvatarEventListCount;
                for (i = PhysicalAvatarEventListStart; i < PhysicalAvatarEventListStart + PhysicalAvatarEventListCount; i++) { PhysicalAvatarEventList[i].ToBytes(packet, ref length); }
                PhysicalAvatarEventListStart += PhysicalAvatarEventListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AnimationListStart < AnimationList.Length ||
                PhysicalAvatarEventListStart < PhysicalAvatarEventList.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AgentRequestSitPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class TargetObjectBlock : PacketBlock
        {
            public UUID TargetID;
            public Vector3 Offset;

            public override int Length
            {
                get
                {
                    return 28;
                }
            }

            public TargetObjectBlock() { }
            public TargetObjectBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    TargetID.FromBytes(bytes, i); i += 16;
                    Offset.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TargetID.ToBytes(bytes, i); i += 16;
                Offset.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += AgentData.Length;
                length += TargetObject.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public TargetObjectBlock TargetObject;

        public AgentRequestSitPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentRequestSit;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 6;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            TargetObject = new TargetObjectBlock();
        }

        public AgentRequestSitPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            TargetObject.FromBytes(bytes, ref i);
        }

        public AgentRequestSitPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            TargetObject.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            length += TargetObject.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            TargetObject.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AgentSitPacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public AgentSitPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AgentSit;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 7;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public AgentSitPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public AgentSitPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class RequestImagePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class RequestImageBlock : PacketBlock
        {
            public UUID Image;
            public sbyte DiscardLevel;
            public float DownloadPriority;
            public uint Packet;
            public byte Type;

            public override int Length
            {
                get
                {
                    return 26;
                }
            }

            public RequestImageBlock() { }
            public RequestImageBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Image.FromBytes(bytes, i); i += 16;
                    DiscardLevel = (sbyte)bytes[i++];
                    DownloadPriority = Utils.BytesToFloat(bytes, i); i += 4;
                    Packet = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Type = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Image.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)DiscardLevel;
                Utils.FloatToBytes(DownloadPriority, bytes, i); i += 4;
                Utils.UIntToBytes(Packet, bytes, i); i += 4;
                bytes[i++] = Type;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += AgentData.Length;
                for (int j = 0; j < RequestImage.Length; j++)
                    length += RequestImage[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public RequestImageBlock[] RequestImage;

        public RequestImagePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.RequestImage;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 8;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
            RequestImage = null;
        }

        public RequestImagePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RequestImage == null || RequestImage.Length != -1) {
                RequestImage = new RequestImageBlock[count];
                for(int j = 0; j < count; j++)
                { RequestImage[j] = new RequestImageBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RequestImage[j].FromBytes(bytes, ref i); }
        }

        public RequestImagePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(RequestImage == null || RequestImage.Length != count) {
                RequestImage = new RequestImageBlock[count];
                for(int j = 0; j < count; j++)
                { RequestImage[j] = new RequestImageBlock(); }
            }
            for (int j = 0; j < count; j++)
            { RequestImage[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < RequestImage.Length; j++) { length += RequestImage[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)RequestImage.Length;
            for (int j = 0; j < RequestImage.Length; j++) { RequestImage[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int RequestImageStart = 0;
            do
            {
                int variableLength = 0;
                int RequestImageCount = 0;

                i = RequestImageStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < RequestImage.Length) {
                    int blockLength = RequestImage[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++RequestImageCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)RequestImageCount;
                for (i = RequestImageStart; i < RequestImageStart + RequestImageCount; i++) { RequestImage[i].ToBytes(packet, ref length); }
                RequestImageStart += RequestImageCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                RequestImageStart < RequestImage.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ImageDataPacket : Packet
    {
        /// <exclude/>
        public sealed class ImageIDBlock : PacketBlock
        {
            public UUID ID;
            public byte Codec;
            public uint Size;
            public ushort Packets;

            public override int Length
            {
                get
                {
                    return 23;
                }
            }

            public ImageIDBlock() { }
            public ImageIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    Codec = (byte)bytes[i++];
                    Size = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Packets = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = Codec;
                Utils.UIntToBytes(Size, bytes, i); i += 4;
                bytes[i++] = (byte)(Packets % 256);
                bytes[i++] = (byte)((Packets >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ImageDataBlock : PacketBlock
        {
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public ImageDataBlock() { }
            public ImageDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += ImageID.Length;
                length += ImageData.Length;
                return length;
            }
        }
        public ImageIDBlock ImageID;
        public ImageDataBlock ImageData;

        public ImageDataPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ImageData;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 9;
            Header.Reliable = true;
            ImageID = new ImageIDBlock();
            ImageData = new ImageDataBlock();
        }

        public ImageDataPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ImageID.FromBytes(bytes, ref i);
            ImageData.FromBytes(bytes, ref i);
        }

        public ImageDataPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ImageID.FromBytes(bytes, ref i);
            ImageData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += ImageID.Length;
            length += ImageData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ImageID.ToBytes(bytes, ref i);
            ImageData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ImagePacketPacket : Packet
    {
        /// <exclude/>
        public sealed class ImageIDBlock : PacketBlock
        {
            public UUID ID;
            public ushort Packet;

            public override int Length
            {
                get
                {
                    return 18;
                }
            }

            public ImageIDBlock() { }
            public ImageIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                    Packet = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)(Packet % 256);
                bytes[i++] = (byte)((Packet >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ImageDataBlock : PacketBlock
        {
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public ImageDataBlock() { }
            public ImageDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += ImageID.Length;
                length += ImageData.Length;
                return length;
            }
        }
        public ImageIDBlock ImageID;
        public ImageDataBlock ImageData;

        public ImagePacketPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ImagePacket;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 10;
            Header.Reliable = true;
            ImageID = new ImageIDBlock();
            ImageData = new ImageDataBlock();
        }

        public ImagePacketPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ImageID.FromBytes(bytes, ref i);
            ImageData.FromBytes(bytes, ref i);
        }

        public ImagePacketPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ImageID.FromBytes(bytes, ref i);
            ImageData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += ImageID.Length;
            length += ImageData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ImageID.ToBytes(bytes, ref i);
            ImageData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class LayerDataPacket : Packet
    {
        /// <exclude/>
        public sealed class LayerIDBlock : PacketBlock
        {
            public byte Type;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public LayerIDBlock() { }
            public LayerIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Type = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = Type;
            }

        }

        /// <exclude/>
        public sealed class LayerDataBlock : PacketBlock
        {
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public LayerDataBlock() { }
            public LayerDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += LayerID.Length;
                length += LayerData.Length;
                return length;
            }
        }
        public LayerIDBlock LayerID;
        public LayerDataBlock LayerData;

        public LayerDataPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.LayerData;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 11;
            Header.Reliable = true;
            LayerID = new LayerIDBlock();
            LayerData = new LayerDataBlock();
        }

        public LayerDataPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            LayerID.FromBytes(bytes, ref i);
            LayerData.FromBytes(bytes, ref i);
        }

        public LayerDataPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            LayerID.FromBytes(bytes, ref i);
            LayerData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += LayerID.Length;
            length += LayerData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            LayerID.ToBytes(bytes, ref i);
            LayerData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ObjectUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class RegionDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public ushort TimeDilation;

            public override int Length
            {
                get
                {
                    return 10;
                }
            }

            public RegionDataBlock() { }
            public RegionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    TimeDilation = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = (byte)(TimeDilation % 256);
                bytes[i++] = (byte)((TimeDilation >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ID;
            public byte State;
            public UUID FullID;
            public uint CRC;
            public byte PCode;
            public byte Material;
            public byte ClickAction;
            public Vector3 Scale;
            public byte[] ObjectData;
            public uint ParentID;
            public uint UpdateFlags;
            public byte PathCurve;
            public byte ProfileCurve;
            public ushort PathBegin;
            public ushort PathEnd;
            public byte PathScaleX;
            public byte PathScaleY;
            public byte PathShearX;
            public byte PathShearY;
            public sbyte PathTwist;
            public sbyte PathTwistBegin;
            public sbyte PathRadiusOffset;
            public sbyte PathTaperX;
            public sbyte PathTaperY;
            public byte PathRevolutions;
            public sbyte PathSkew;
            public ushort ProfileBegin;
            public ushort ProfileEnd;
            public ushort ProfileHollow;
            public byte[] TextureEntry;
            public byte[] TextureAnim;
            public byte[] NameValue;
            public byte[] Data;
            public byte[] Text;
            public byte[] TextColor;
            public byte[] MediaURL;
            public byte[] PSBlock;
            public byte[] ExtraParams;
            public UUID Sound;
            public UUID OwnerID;
            public float Gain;
            public byte Flags;
            public float Radius;
            public byte JointType;
            public Vector3 JointPivot;
            public Vector3 JointAxisOrAnchor;

            public override int Length
            {
                get
                {
                    int length = 153;
                    if (ObjectData != null) { length += ObjectData.Length; }
                    if (TextureEntry != null) { length += TextureEntry.Length; }
                    if (TextureAnim != null) { length += TextureAnim.Length; }
                    if (NameValue != null) { length += NameValue.Length; }
                    if (Data != null) { length += Data.Length; }
                    if (Text != null) { length += Text.Length; }
                    if (MediaURL != null) { length += MediaURL.Length; }
                    if (PSBlock != null) { length += PSBlock.Length; }
                    if (ExtraParams != null) { length += ExtraParams.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    ID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    State = (byte)bytes[i++];
                    FullID.FromBytes(bytes, i); i += 16;
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PCode = (byte)bytes[i++];
                    Material = (byte)bytes[i++];
                    ClickAction = (byte)bytes[i++];
                    Scale.FromBytes(bytes, i); i += 12;
                    length = bytes[i++];
                    ObjectData = new byte[length];
                    Buffer.BlockCopy(bytes, i, ObjectData, 0, length); i += length;
                    ParentID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    UpdateFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PathCurve = (byte)bytes[i++];
                    ProfileCurve = (byte)bytes[i++];
                    PathBegin = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    PathEnd = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    PathScaleX = (byte)bytes[i++];
                    PathScaleY = (byte)bytes[i++];
                    PathShearX = (byte)bytes[i++];
                    PathShearY = (byte)bytes[i++];
                    PathTwist = (sbyte)bytes[i++];
                    PathTwistBegin = (sbyte)bytes[i++];
                    PathRadiusOffset = (sbyte)bytes[i++];
                    PathTaperX = (sbyte)bytes[i++];
                    PathTaperY = (sbyte)bytes[i++];
                    PathRevolutions = (byte)bytes[i++];
                    PathSkew = (sbyte)bytes[i++];
                    ProfileBegin = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ProfileEnd = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    ProfileHollow = (ushort)(bytes[i++] + (bytes[i++] << 8));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    TextureEntry = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureEntry, 0, length); i += length;
                    length = bytes[i++];
                    TextureAnim = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureAnim, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    NameValue = new byte[length];
                    Buffer.BlockCopy(bytes, i, NameValue, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                    length = bytes[i++];
                    Text = new byte[length];
                    Buffer.BlockCopy(bytes, i, Text, 0, length); i += length;
                    TextColor = new byte[4];
                    Buffer.BlockCopy(bytes, i, TextColor, 0, 4); i += 4;
                    length = bytes[i++];
                    MediaURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaURL, 0, length); i += length;
                    length = bytes[i++];
                    PSBlock = new byte[length];
                    Buffer.BlockCopy(bytes, i, PSBlock, 0, length); i += length;
                    length = bytes[i++];
                    ExtraParams = new byte[length];
                    Buffer.BlockCopy(bytes, i, ExtraParams, 0, length); i += length;
                    Sound.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    Gain = Utils.BytesToFloat(bytes, i); i += 4;
                    Flags = (byte)bytes[i++];
                    Radius = Utils.BytesToFloat(bytes, i); i += 4;
                    JointType = (byte)bytes[i++];
                    JointPivot.FromBytes(bytes, i); i += 12;
                    JointAxisOrAnchor.FromBytes(bytes, i); i += 12;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ID, bytes, i); i += 4;
                bytes[i++] = State;
                FullID.ToBytes(bytes, i); i += 16;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
                bytes[i++] = PCode;
                bytes[i++] = Material;
                bytes[i++] = ClickAction;
                Scale.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)ObjectData.Length;
                Buffer.BlockCopy(ObjectData, 0, bytes, i, ObjectData.Length); i += ObjectData.Length;
                Utils.UIntToBytes(ParentID, bytes, i); i += 4;
                Utils.UIntToBytes(UpdateFlags, bytes, i); i += 4;
                bytes[i++] = PathCurve;
                bytes[i++] = ProfileCurve;
                bytes[i++] = (byte)(PathBegin % 256);
                bytes[i++] = (byte)((PathBegin >> 8) % 256);
                bytes[i++] = (byte)(PathEnd % 256);
                bytes[i++] = (byte)((PathEnd >> 8) % 256);
                bytes[i++] = PathScaleX;
                bytes[i++] = PathScaleY;
                bytes[i++] = PathShearX;
                bytes[i++] = PathShearY;
                bytes[i++] = (byte)PathTwist;
                bytes[i++] = (byte)PathTwistBegin;
                bytes[i++] = (byte)PathRadiusOffset;
                bytes[i++] = (byte)PathTaperX;
                bytes[i++] = (byte)PathTaperY;
                bytes[i++] = PathRevolutions;
                bytes[i++] = (byte)PathSkew;
                bytes[i++] = (byte)(ProfileBegin % 256);
                bytes[i++] = (byte)((ProfileBegin >> 8) % 256);
                bytes[i++] = (byte)(ProfileEnd % 256);
                bytes[i++] = (byte)((ProfileEnd >> 8) % 256);
                bytes[i++] = (byte)(ProfileHollow % 256);
                bytes[i++] = (byte)((ProfileHollow >> 8) % 256);
                bytes[i++] = (byte)(TextureEntry.Length % 256);
                bytes[i++] = (byte)((TextureEntry.Length >> 8) % 256);
                Buffer.BlockCopy(TextureEntry, 0, bytes, i, TextureEntry.Length); i += TextureEntry.Length;
                bytes[i++] = (byte)TextureAnim.Length;
                Buffer.BlockCopy(TextureAnim, 0, bytes, i, TextureAnim.Length); i += TextureAnim.Length;
                bytes[i++] = (byte)(NameValue.Length % 256);
                bytes[i++] = (byte)((NameValue.Length >> 8) % 256);
                Buffer.BlockCopy(NameValue, 0, bytes, i, NameValue.Length); i += NameValue.Length;
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
                bytes[i++] = (byte)Text.Length;
                Buffer.BlockCopy(Text, 0, bytes, i, Text.Length); i += Text.Length;
                Buffer.BlockCopy(TextColor, 0, bytes, i, 4);i += 4;
                bytes[i++] = (byte)MediaURL.Length;
                Buffer.BlockCopy(MediaURL, 0, bytes, i, MediaURL.Length); i += MediaURL.Length;
                bytes[i++] = (byte)PSBlock.Length;
                Buffer.BlockCopy(PSBlock, 0, bytes, i, PSBlock.Length); i += PSBlock.Length;
                bytes[i++] = (byte)ExtraParams.Length;
                Buffer.BlockCopy(ExtraParams, 0, bytes, i, ExtraParams.Length); i += ExtraParams.Length;
                Sound.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                Utils.FloatToBytes(Gain, bytes, i); i += 4;
                bytes[i++] = Flags;
                Utils.FloatToBytes(Radius, bytes, i); i += 4;
                bytes[i++] = JointType;
                JointPivot.ToBytes(bytes, i); i += 12;
                JointAxisOrAnchor.ToBytes(bytes, i); i += 12;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += RegionData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public RegionDataBlock RegionData;
        public ObjectDataBlock[] ObjectData;

        public ObjectUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 12;
            Header.Reliable = true;
            Header.Zerocoded = true;
            RegionData = new RegionDataBlock();
            ObjectData = null;
        }

        public ObjectUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += RegionData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RegionData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += RegionData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            RegionData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectUpdateCompressedPacket : Packet
    {
        /// <exclude/>
        public sealed class RegionDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public ushort TimeDilation;

            public override int Length
            {
                get
                {
                    return 10;
                }
            }

            public RegionDataBlock() { }
            public RegionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    TimeDilation = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = (byte)(TimeDilation % 256);
                bytes[i++] = (byte)((TimeDilation >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint UpdateFlags;
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 6;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    UpdateFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(UpdateFlags, bytes, i); i += 4;
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += RegionData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public RegionDataBlock RegionData;
        public ObjectDataBlock[] ObjectData;

        public ObjectUpdateCompressedPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectUpdateCompressed;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 13;
            Header.Reliable = true;
            RegionData = new RegionDataBlock();
            ObjectData = null;
        }

        public ObjectUpdateCompressedPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectUpdateCompressedPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += RegionData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RegionData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += RegionData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            RegionData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ObjectUpdateCachedPacket : Packet
    {
        /// <exclude/>
        public sealed class RegionDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public ushort TimeDilation;

            public override int Length
            {
                get
                {
                    return 10;
                }
            }

            public RegionDataBlock() { }
            public RegionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    TimeDilation = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = (byte)(TimeDilation % 256);
                bytes[i++] = (byte)((TimeDilation >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ID;
            public uint CRC;
            public uint UpdateFlags;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    CRC = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    UpdateFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ID, bytes, i); i += 4;
                Utils.UIntToBytes(CRC, bytes, i); i += 4;
                Utils.UIntToBytes(UpdateFlags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += RegionData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public RegionDataBlock RegionData;
        public ObjectDataBlock[] ObjectData;

        public ObjectUpdateCachedPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ObjectUpdateCached;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 14;
            Header.Reliable = true;
            RegionData = new RegionDataBlock();
            ObjectData = null;
        }

        public ObjectUpdateCachedPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ObjectUpdateCachedPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += RegionData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RegionData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += RegionData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            RegionData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ImprovedTerseObjectUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class RegionDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public ushort TimeDilation;

            public override int Length
            {
                get
                {
                    return 10;
                }
            }

            public RegionDataBlock() { }
            public RegionDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    TimeDilation = (ushort)(bytes[i++] + (bytes[i++] << 8));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                bytes[i++] = (byte)(TimeDilation % 256);
                bytes[i++] = (byte)((TimeDilation >> 8) % 256);
            }

        }

        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public byte[] Data;
            public byte[] TextureEntry;

            public override int Length
            {
                get
                {
                    int length = 3;
                    if (Data != null) { length += Data.Length; }
                    if (TextureEntry != null) { length += TextureEntry.Length; }
                    return length;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    TextureEntry = new byte[length];
                    Buffer.BlockCopy(bytes, i, TextureEntry, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)Data.Length;
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
                bytes[i++] = (byte)(TextureEntry.Length % 256);
                bytes[i++] = (byte)((TextureEntry.Length >> 8) % 256);
                Buffer.BlockCopy(TextureEntry, 0, bytes, i, TextureEntry.Length); i += TextureEntry.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                length += RegionData.Length;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public RegionDataBlock RegionData;
        public ObjectDataBlock[] ObjectData;

        public ImprovedTerseObjectUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ImprovedTerseObjectUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 15;
            Header.Reliable = true;
            RegionData = new RegionDataBlock();
            ObjectData = null;
        }

        public ImprovedTerseObjectUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public ImprovedTerseObjectUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            RegionData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += RegionData.Length;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            RegionData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += RegionData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            RegionData.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class KillObjectPacket : Packet
    {
        /// <exclude/>
        public sealed class ObjectDataBlock : PacketBlock
        {
            public uint ID;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public ObjectDataBlock() { }
            public ObjectDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(ID, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 8;
                for (int j = 0; j < ObjectData.Length; j++)
                    length += ObjectData[j].Length;
                return length;
            }
        }
        public ObjectDataBlock[] ObjectData;

        public KillObjectPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.KillObject;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 16;
            Header.Reliable = true;
            ObjectData = null;
        }

        public KillObjectPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != -1) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public KillObjectPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            int count = (int)bytes[i++];
            if(ObjectData == null || ObjectData.Length != count) {
                ObjectData = new ObjectDataBlock[count];
                for(int j = 0; j < count; j++)
                { ObjectData[j] = new ObjectDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { ObjectData[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length++;
            for (int j = 0; j < ObjectData.Length; j++) { length += ObjectData[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            bytes[i++] = (byte)ObjectData.Length;
            for (int j = 0; j < ObjectData.Length; j++) { ObjectData[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            fixedLength += 1;

            int ObjectDataStart = 0;
            do
            {
                int variableLength = 0;
                int ObjectDataCount = 0;

                i = ObjectDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < ObjectData.Length) {
                    int blockLength = ObjectData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++ObjectDataCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)ObjectDataCount;
                for (i = ObjectDataStart; i < ObjectDataStart + ObjectDataCount; i++) { ObjectData[i].ToBytes(packet, ref length); }
                ObjectDataStart += ObjectDataCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                ObjectDataStart < ObjectData.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class TransferPacketPacket : Packet
    {
        /// <exclude/>
        public sealed class TransferDataBlock : PacketBlock
        {
            public UUID TransferID;
            public int ChannelType;
            public int Packet;
            public int Status;
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 30;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public TransferDataBlock() { }
            public TransferDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    TransferID.FromBytes(bytes, i); i += 16;
                    ChannelType = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Packet = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Status = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                TransferID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(ChannelType, bytes, i); i += 4;
                Utils.IntToBytes(Packet, bytes, i); i += 4;
                Utils.IntToBytes(Status, bytes, i); i += 4;
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += TransferData.Length;
                return length;
            }
        }
        public TransferDataBlock TransferData;

        public TransferPacketPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.TransferPacket;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 17;
            Header.Reliable = true;
            TransferData = new TransferDataBlock();
        }

        public TransferPacketPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            TransferData.FromBytes(bytes, ref i);
        }

        public TransferPacketPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            TransferData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += TransferData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            TransferData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SendXferPacketPacket : Packet
    {
        /// <exclude/>
        public sealed class XferIDBlock : PacketBlock
        {
            public ulong ID;
            public uint Packet;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public XferIDBlock() { }
            public XferIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Packet = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(ID, bytes, i); i += 8;
                Utils.UIntToBytes(Packet, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class DataPacketBlock : PacketBlock
        {
            public byte[] Data;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (Data != null) { length += Data.Length; }
                    return length;
                }
            }

            public DataPacketBlock() { }
            public DataPacketBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Data = new byte[length];
                    Buffer.BlockCopy(bytes, i, Data, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(Data.Length % 256);
                bytes[i++] = (byte)((Data.Length >> 8) % 256);
                Buffer.BlockCopy(Data, 0, bytes, i, Data.Length); i += Data.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += XferID.Length;
                length += DataPacket.Length;
                return length;
            }
        }
        public XferIDBlock XferID;
        public DataPacketBlock DataPacket;

        public SendXferPacketPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SendXferPacket;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 18;
            Header.Reliable = true;
            XferID = new XferIDBlock();
            DataPacket = new DataPacketBlock();
        }

        public SendXferPacketPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            XferID.FromBytes(bytes, ref i);
            DataPacket.FromBytes(bytes, ref i);
        }

        public SendXferPacketPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            XferID.FromBytes(bytes, ref i);
            DataPacket.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += XferID.Length;
            length += DataPacket.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            XferID.ToBytes(bytes, ref i);
            DataPacket.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ConfirmXferPacketPacket : Packet
    {
        /// <exclude/>
        public sealed class XferIDBlock : PacketBlock
        {
            public ulong ID;
            public uint Packet;

            public override int Length
            {
                get
                {
                    return 12;
                }
            }

            public XferIDBlock() { }
            public XferIDBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Packet = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(ID, bytes, i); i += 8;
                Utils.UIntToBytes(Packet, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += XferID.Length;
                return length;
            }
        }
        public XferIDBlock XferID;

        public ConfirmXferPacketPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ConfirmXferPacket;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 19;
            Header.Reliable = true;
            XferID = new XferIDBlock();
        }

        public ConfirmXferPacketPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            XferID.FromBytes(bytes, ref i);
        }

        public ConfirmXferPacketPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            XferID.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += XferID.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            XferID.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class AvatarAnimationPacket : Packet
    {
        /// <exclude/>
        public sealed class SenderBlock : PacketBlock
        {
            public UUID ID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public SenderBlock() { }
            public SenderBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class AnimationListBlock : PacketBlock
        {
            public UUID AnimID;
            public int AnimSequenceID;

            public override int Length
            {
                get
                {
                    return 20;
                }
            }

            public AnimationListBlock() { }
            public AnimationListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AnimID.FromBytes(bytes, i); i += 16;
                    AnimSequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                AnimID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(AnimSequenceID, bytes, i); i += 4;
            }

        }

        /// <exclude/>
        public sealed class AnimationSourceListBlock : PacketBlock
        {
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public AnimationSourceListBlock() { }
            public AnimationSourceListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class PhysicalAvatarEventListBlock : PacketBlock
        {
            public byte[] TypeData;

            public override int Length
            {
                get
                {
                    int length = 1;
                    if (TypeData != null) { length += TypeData.Length; }
                    return length;
                }
            }

            public PhysicalAvatarEventListBlock() { }
            public PhysicalAvatarEventListBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = bytes[i++];
                    TypeData = new byte[length];
                    Buffer.BlockCopy(bytes, i, TypeData, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)TypeData.Length;
                Buffer.BlockCopy(TypeData, 0, bytes, i, TypeData.Length); i += TypeData.Length;
            }

        }

        public override int Length
        {
            get
            {
                int length = 10;
                length += Sender.Length;
                for (int j = 0; j < AnimationList.Length; j++)
                    length += AnimationList[j].Length;
                for (int j = 0; j < AnimationSourceList.Length; j++)
                    length += AnimationSourceList[j].Length;
                for (int j = 0; j < PhysicalAvatarEventList.Length; j++)
                    length += PhysicalAvatarEventList[j].Length;
                return length;
            }
        }
        public SenderBlock Sender;
        public AnimationListBlock[] AnimationList;
        public AnimationSourceListBlock[] AnimationSourceList;
        public PhysicalAvatarEventListBlock[] PhysicalAvatarEventList;

        public AvatarAnimationPacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.AvatarAnimation;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 20;
            Header.Reliable = true;
            Sender = new SenderBlock();
            AnimationList = null;
            AnimationSourceList = null;
            PhysicalAvatarEventList = null;
        }

        public AvatarAnimationPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            Sender.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AnimationList == null || AnimationList.Length != -1) {
                AnimationList = new AnimationListBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationList[j] = new AnimationListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationList[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AnimationSourceList == null || AnimationSourceList.Length != -1) {
                AnimationSourceList = new AnimationSourceListBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationSourceList[j] = new AnimationSourceListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationSourceList[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(PhysicalAvatarEventList == null || PhysicalAvatarEventList.Length != -1) {
                PhysicalAvatarEventList = new PhysicalAvatarEventListBlock[count];
                for(int j = 0; j < count; j++)
                { PhysicalAvatarEventList[j] = new PhysicalAvatarEventListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { PhysicalAvatarEventList[j].FromBytes(bytes, ref i); }
        }

        public AvatarAnimationPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            Sender.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(AnimationList == null || AnimationList.Length != count) {
                AnimationList = new AnimationListBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationList[j] = new AnimationListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationList[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AnimationSourceList == null || AnimationSourceList.Length != count) {
                AnimationSourceList = new AnimationSourceListBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationSourceList[j] = new AnimationSourceListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationSourceList[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(PhysicalAvatarEventList == null || PhysicalAvatarEventList.Length != count) {
                PhysicalAvatarEventList = new PhysicalAvatarEventListBlock[count];
                for(int j = 0; j < count; j++)
                { PhysicalAvatarEventList[j] = new PhysicalAvatarEventListBlock(); }
            }
            for (int j = 0; j < count; j++)
            { PhysicalAvatarEventList[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += Sender.Length;
            length++;
            for (int j = 0; j < AnimationList.Length; j++) { length += AnimationList[j].Length; }
            length++;
            for (int j = 0; j < AnimationSourceList.Length; j++) { length += AnimationSourceList[j].Length; }
            length++;
            for (int j = 0; j < PhysicalAvatarEventList.Length; j++) { length += PhysicalAvatarEventList[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            Sender.ToBytes(bytes, ref i);
            bytes[i++] = (byte)AnimationList.Length;
            for (int j = 0; j < AnimationList.Length; j++) { AnimationList[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)AnimationSourceList.Length;
            for (int j = 0; j < AnimationSourceList.Length; j++) { AnimationSourceList[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)PhysicalAvatarEventList.Length;
            for (int j = 0; j < PhysicalAvatarEventList.Length; j++) { PhysicalAvatarEventList[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += Sender.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            Sender.ToBytes(fixedBytes, ref i);
            fixedLength += 3;

            int AnimationListStart = 0;
            int AnimationSourceListStart = 0;
            int PhysicalAvatarEventListStart = 0;
            do
            {
                int variableLength = 0;
                int AnimationListCount = 0;
                int AnimationSourceListCount = 0;
                int PhysicalAvatarEventListCount = 0;

                i = AnimationListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AnimationList.Length) {
                    int blockLength = AnimationList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AnimationListCount;
                    }
                    else { break; }
                    ++i;
                }

                i = AnimationSourceListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AnimationSourceList.Length) {
                    int blockLength = AnimationSourceList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AnimationSourceListCount;
                    }
                    else { break; }
                    ++i;
                }

                i = PhysicalAvatarEventListStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < PhysicalAvatarEventList.Length) {
                    int blockLength = PhysicalAvatarEventList[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++PhysicalAvatarEventListCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)AnimationListCount;
                for (i = AnimationListStart; i < AnimationListStart + AnimationListCount; i++) { AnimationList[i].ToBytes(packet, ref length); }
                AnimationListStart += AnimationListCount;

                packet[length++] = (byte)AnimationSourceListCount;
                for (i = AnimationSourceListStart; i < AnimationSourceListStart + AnimationSourceListCount; i++) { AnimationSourceList[i].ToBytes(packet, ref length); }
                AnimationSourceListStart += AnimationSourceListCount;

                packet[length++] = (byte)PhysicalAvatarEventListCount;
                for (i = PhysicalAvatarEventListStart; i < PhysicalAvatarEventListStart + PhysicalAvatarEventListCount; i++) { PhysicalAvatarEventList[i].ToBytes(packet, ref length); }
                PhysicalAvatarEventListStart += PhysicalAvatarEventListCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                AnimationListStart < AnimationList.Length ||
                AnimationSourceListStart < AnimationSourceList.Length ||
                PhysicalAvatarEventListStart < PhysicalAvatarEventList.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class AvatarSitResponsePacket : Packet
    {
        /// <exclude/>
        public sealed class SitObjectBlock : PacketBlock
        {
            public UUID ID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public SitObjectBlock() { }
            public SitObjectBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                ID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class SitTransformBlock : PacketBlock
        {
            public bool AutoPilot;
            public Vector3 SitPosition;
            public Quaternion SitRotation;
            public Vector3 CameraEyeOffset;
            public Vector3 CameraAtOffset;
            public bool ForceMouselook;

            public override int Length
            {
                get
                {
                    return 50;
                }
            }

            public SitTransformBlock() { }
            public SitTransformBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AutoPilot = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    SitPosition.FromBytes(bytes, i); i += 12;
                    SitRotation.FromBytes(bytes, i, true); i += 12;
                    CameraEyeOffset.FromBytes(bytes, i); i += 12;
                    CameraAtOffset.FromBytes(bytes, i); i += 12;
                    ForceMouselook = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((AutoPilot) ? 1 : 0);
                SitPosition.ToBytes(bytes, i); i += 12;
                SitRotation.ToBytes(bytes, i); i += 12;
                CameraEyeOffset.ToBytes(bytes, i); i += 12;
                CameraAtOffset.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)((ForceMouselook) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += SitObject.Length;
                length += SitTransform.Length;
                return length;
            }
        }
        public SitObjectBlock SitObject;
        public SitTransformBlock SitTransform;

        public AvatarSitResponsePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.AvatarSitResponse;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 21;
            Header.Reliable = true;
            Header.Zerocoded = true;
            SitObject = new SitObjectBlock();
            SitTransform = new SitTransformBlock();
        }

        public AvatarSitResponsePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            SitObject.FromBytes(bytes, ref i);
            SitTransform.FromBytes(bytes, ref i);
        }

        public AvatarSitResponsePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            SitObject.FromBytes(bytes, ref i);
            SitTransform.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += SitObject.Length;
            length += SitTransform.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            SitObject.ToBytes(bytes, ref i);
            SitTransform.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class CameraConstraintPacket : Packet
    {
        /// <exclude/>
        public sealed class CameraCollidePlaneBlock : PacketBlock
        {
            public Vector4 Plane;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public CameraCollidePlaneBlock() { }
            public CameraCollidePlaneBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Plane.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Plane.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += CameraCollidePlane.Length;
                return length;
            }
        }
        public CameraCollidePlaneBlock CameraCollidePlane;

        public CameraConstraintPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.CameraConstraint;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 22;
            Header.Reliable = true;
            Header.Zerocoded = true;
            CameraCollidePlane = new CameraCollidePlaneBlock();
        }

        public CameraConstraintPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            CameraCollidePlane.FromBytes(bytes, ref i);
        }

        public CameraConstraintPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            CameraCollidePlane.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += CameraCollidePlane.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            CameraCollidePlane.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ParcelPropertiesPacket : Packet
    {
        /// <exclude/>
        public sealed class ParcelDataBlock : PacketBlock
        {
            public int RequestResult;
            public int SequenceID;
            public bool SnapSelection;
            public int SelfCount;
            public int OtherCount;
            public int PublicCount;
            public int LocalID;
            public UUID OwnerID;
            public bool IsGroupOwned;
            public uint AuctionID;
            public int ClaimDate;
            public int ClaimPrice;
            public int RentPrice;
            public Vector3 AABBMin;
            public Vector3 AABBMax;
            public byte[] Bitmap;
            public int Area;
            public byte Status;
            public int SimWideMaxPrims;
            public int SimWideTotalPrims;
            public int MaxPrims;
            public int TotalPrims;
            public int OwnerPrims;
            public int GroupPrims;
            public int OtherPrims;
            public int SelectedPrims;
            public float ParcelPrimBonus;
            public int OtherCleanTime;
            public uint ParcelFlags;
            public int SalePrice;
            public byte[] Name;
            public byte[] Desc;
            public byte[] MusicURL;
            public byte[] MediaURL;
            public UUID MediaID;
            public byte MediaAutoScale;
            public UUID GroupID;
            public int PassPrice;
            public float PassHours;
            public byte Category;
            public UUID AuthBuyerID;
            public UUID SnapshotID;
            public Vector3 UserLocation;
            public Vector3 UserLookAt;
            public byte LandingType;
            public bool RegionPushOverride;
            public bool RegionDenyAnonymous;
            public bool RegionDenyIdentified;
            public bool RegionDenyTransacted;

            public override int Length
            {
                get
                {
                    int length = 244;
                    if (Bitmap != null) { length += Bitmap.Length; }
                    if (Name != null) { length += Name.Length; }
                    if (Desc != null) { length += Desc.Length; }
                    if (MusicURL != null) { length += MusicURL.Length; }
                    if (MediaURL != null) { length += MediaURL.Length; }
                    return length;
                }
            }

            public ParcelDataBlock() { }
            public ParcelDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RequestResult = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SequenceID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SnapSelection = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    SelfCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OtherCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PublicCount = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    LocalID = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerID.FromBytes(bytes, i); i += 16;
                    IsGroupOwned = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    AuctionID = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ClaimDate = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ClaimPrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    RentPrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AABBMin.FromBytes(bytes, i); i += 12;
                    AABBMax.FromBytes(bytes, i); i += 12;
                    length = (bytes[i++] + (bytes[i++] << 8));
                    Bitmap = new byte[length];
                    Buffer.BlockCopy(bytes, i, Bitmap, 0, length); i += length;
                    Area = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    Status = (byte)bytes[i++];
                    SimWideMaxPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SimWideTotalPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    MaxPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    TotalPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OwnerPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    GroupPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    OtherPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SelectedPrims = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelPrimBonus = Utils.BytesToFloat(bytes, i); i += 4;
                    OtherCleanTime = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    ParcelFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    SalePrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    length = bytes[i++];
                    Name = new byte[length];
                    Buffer.BlockCopy(bytes, i, Name, 0, length); i += length;
                    length = bytes[i++];
                    Desc = new byte[length];
                    Buffer.BlockCopy(bytes, i, Desc, 0, length); i += length;
                    length = bytes[i++];
                    MusicURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MusicURL, 0, length); i += length;
                    length = bytes[i++];
                    MediaURL = new byte[length];
                    Buffer.BlockCopy(bytes, i, MediaURL, 0, length); i += length;
                    MediaID.FromBytes(bytes, i); i += 16;
                    MediaAutoScale = (byte)bytes[i++];
                    GroupID.FromBytes(bytes, i); i += 16;
                    PassPrice = (int)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    PassHours = Utils.BytesToFloat(bytes, i); i += 4;
                    Category = (byte)bytes[i++];
                    AuthBuyerID.FromBytes(bytes, i); i += 16;
                    SnapshotID.FromBytes(bytes, i); i += 16;
                    UserLocation.FromBytes(bytes, i); i += 12;
                    UserLookAt.FromBytes(bytes, i); i += 12;
                    LandingType = (byte)bytes[i++];
                    RegionPushOverride = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RegionDenyAnonymous = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RegionDenyIdentified = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    RegionDenyTransacted = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.IntToBytes(RequestResult, bytes, i); i += 4;
                Utils.IntToBytes(SequenceID, bytes, i); i += 4;
                bytes[i++] = (byte)((SnapSelection) ? 1 : 0);
                Utils.IntToBytes(SelfCount, bytes, i); i += 4;
                Utils.IntToBytes(OtherCount, bytes, i); i += 4;
                Utils.IntToBytes(PublicCount, bytes, i); i += 4;
                Utils.IntToBytes(LocalID, bytes, i); i += 4;
                OwnerID.ToBytes(bytes, i); i += 16;
                bytes[i++] = (byte)((IsGroupOwned) ? 1 : 0);
                Utils.UIntToBytes(AuctionID, bytes, i); i += 4;
                Utils.IntToBytes(ClaimDate, bytes, i); i += 4;
                Utils.IntToBytes(ClaimPrice, bytes, i); i += 4;
                Utils.IntToBytes(RentPrice, bytes, i); i += 4;
                AABBMin.ToBytes(bytes, i); i += 12;
                AABBMax.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)(Bitmap.Length % 256);
                bytes[i++] = (byte)((Bitmap.Length >> 8) % 256);
                Buffer.BlockCopy(Bitmap, 0, bytes, i, Bitmap.Length); i += Bitmap.Length;
                Utils.IntToBytes(Area, bytes, i); i += 4;
                bytes[i++] = Status;
                Utils.IntToBytes(SimWideMaxPrims, bytes, i); i += 4;
                Utils.IntToBytes(SimWideTotalPrims, bytes, i); i += 4;
                Utils.IntToBytes(MaxPrims, bytes, i); i += 4;
                Utils.IntToBytes(TotalPrims, bytes, i); i += 4;
                Utils.IntToBytes(OwnerPrims, bytes, i); i += 4;
                Utils.IntToBytes(GroupPrims, bytes, i); i += 4;
                Utils.IntToBytes(OtherPrims, bytes, i); i += 4;
                Utils.IntToBytes(SelectedPrims, bytes, i); i += 4;
                Utils.FloatToBytes(ParcelPrimBonus, bytes, i); i += 4;
                Utils.IntToBytes(OtherCleanTime, bytes, i); i += 4;
                Utils.UIntToBytes(ParcelFlags, bytes, i); i += 4;
                Utils.IntToBytes(SalePrice, bytes, i); i += 4;
                bytes[i++] = (byte)Name.Length;
                Buffer.BlockCopy(Name, 0, bytes, i, Name.Length); i += Name.Length;
                bytes[i++] = (byte)Desc.Length;
                Buffer.BlockCopy(Desc, 0, bytes, i, Desc.Length); i += Desc.Length;
                bytes[i++] = (byte)MusicURL.Length;
                Buffer.BlockCopy(MusicURL, 0, bytes, i, MusicURL.Length); i += MusicURL.Length;
                bytes[i++] = (byte)MediaURL.Length;
                Buffer.BlockCopy(MediaURL, 0, bytes, i, MediaURL.Length); i += MediaURL.Length;
                MediaID.ToBytes(bytes, i); i += 16;
                bytes[i++] = MediaAutoScale;
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.IntToBytes(PassPrice, bytes, i); i += 4;
                Utils.FloatToBytes(PassHours, bytes, i); i += 4;
                bytes[i++] = Category;
                AuthBuyerID.ToBytes(bytes, i); i += 16;
                SnapshotID.ToBytes(bytes, i); i += 16;
                UserLocation.ToBytes(bytes, i); i += 12;
                UserLookAt.ToBytes(bytes, i); i += 12;
                bytes[i++] = LandingType;
                bytes[i++] = (byte)((RegionPushOverride) ? 1 : 0);
                bytes[i++] = (byte)((RegionDenyAnonymous) ? 1 : 0);
                bytes[i++] = (byte)((RegionDenyIdentified) ? 1 : 0);
                bytes[i++] = (byte)((RegionDenyTransacted) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class AgeVerificationBlockBlock : PacketBlock
        {
            public bool RegionDenyAgeUnverified;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public AgeVerificationBlockBlock() { }
            public AgeVerificationBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionDenyAgeUnverified = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)((RegionDenyAgeUnverified) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += ParcelData.Length;
                length += AgeVerificationBlock.Length;
                return length;
            }
        }
        public ParcelDataBlock ParcelData;
        public AgeVerificationBlockBlock AgeVerificationBlock;

        public ParcelPropertiesPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ParcelProperties;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 23;
            Header.Reliable = true;
            Header.Zerocoded = true;
            ParcelData = new ParcelDataBlock();
            AgeVerificationBlock = new AgeVerificationBlockBlock();
        }

        public ParcelPropertiesPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            ParcelData.FromBytes(bytes, ref i);
            AgeVerificationBlock.FromBytes(bytes, ref i);
        }

        public ParcelPropertiesPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            ParcelData.FromBytes(bytes, ref i);
            AgeVerificationBlock.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += ParcelData.Length;
            length += AgeVerificationBlock.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            ParcelData.ToBytes(bytes, ref i);
            AgeVerificationBlock.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ChildAgentUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public uint ViewerCircuitCode;
            public UUID AgentID;
            public UUID SessionID;
            public Vector3 AgentPos;
            public Vector3 AgentVel;
            public Vector3 Center;
            public Vector3 Size;
            public Vector3 AtAxis;
            public Vector3 LeftAxis;
            public Vector3 UpAxis;
            public bool ChangedGrid;
            public float Far;
            public float Aspect;
            public byte[] Throttles;
            public uint LocomotionState;
            public Quaternion HeadRotation;
            public Quaternion BodyRotation;
            public uint ControlFlags;
            public float EnergyLevel;
            public byte GodLevel;
            public bool AlwaysRun;
            public UUID PreyAgent;
            public byte AgentAccess;
            public byte[] AgentTextures;
            public UUID ActiveGroupID;

            public override int Length
            {
                get
                {
                    int length = 211;
                    if (Throttles != null) { length += Throttles.Length; }
                    if (AgentTextures != null) { length += AgentTextures.Length; }
                    return length;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    ViewerCircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    AgentPos.FromBytes(bytes, i); i += 12;
                    AgentVel.FromBytes(bytes, i); i += 12;
                    Center.FromBytes(bytes, i); i += 12;
                    Size.FromBytes(bytes, i); i += 12;
                    AtAxis.FromBytes(bytes, i); i += 12;
                    LeftAxis.FromBytes(bytes, i); i += 12;
                    UpAxis.FromBytes(bytes, i); i += 12;
                    ChangedGrid = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    Far = Utils.BytesToFloat(bytes, i); i += 4;
                    Aspect = Utils.BytesToFloat(bytes, i); i += 4;
                    length = bytes[i++];
                    Throttles = new byte[length];
                    Buffer.BlockCopy(bytes, i, Throttles, 0, length); i += length;
                    LocomotionState = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    HeadRotation.FromBytes(bytes, i, true); i += 12;
                    BodyRotation.FromBytes(bytes, i, true); i += 12;
                    ControlFlags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    EnergyLevel = Utils.BytesToFloat(bytes, i); i += 4;
                    GodLevel = (byte)bytes[i++];
                    AlwaysRun = (bytes[i++] != 0) ? (bool)true : (bool)false;
                    PreyAgent.FromBytes(bytes, i); i += 16;
                    AgentAccess = (byte)bytes[i++];
                    length = (bytes[i++] + (bytes[i++] << 8));
                    AgentTextures = new byte[length];
                    Buffer.BlockCopy(bytes, i, AgentTextures, 0, length); i += length;
                    ActiveGroupID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                Utils.UIntToBytes(ViewerCircuitCode, bytes, i); i += 4;
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                AgentPos.ToBytes(bytes, i); i += 12;
                AgentVel.ToBytes(bytes, i); i += 12;
                Center.ToBytes(bytes, i); i += 12;
                Size.ToBytes(bytes, i); i += 12;
                AtAxis.ToBytes(bytes, i); i += 12;
                LeftAxis.ToBytes(bytes, i); i += 12;
                UpAxis.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)((ChangedGrid) ? 1 : 0);
                Utils.FloatToBytes(Far, bytes, i); i += 4;
                Utils.FloatToBytes(Aspect, bytes, i); i += 4;
                bytes[i++] = (byte)Throttles.Length;
                Buffer.BlockCopy(Throttles, 0, bytes, i, Throttles.Length); i += Throttles.Length;
                Utils.UIntToBytes(LocomotionState, bytes, i); i += 4;
                HeadRotation.ToBytes(bytes, i); i += 12;
                BodyRotation.ToBytes(bytes, i); i += 12;
                Utils.UIntToBytes(ControlFlags, bytes, i); i += 4;
                Utils.FloatToBytes(EnergyLevel, bytes, i); i += 4;
                bytes[i++] = GodLevel;
                bytes[i++] = (byte)((AlwaysRun) ? 1 : 0);
                PreyAgent.ToBytes(bytes, i); i += 16;
                bytes[i++] = AgentAccess;
                bytes[i++] = (byte)(AgentTextures.Length % 256);
                bytes[i++] = (byte)((AgentTextures.Length >> 8) % 256);
                Buffer.BlockCopy(AgentTextures, 0, bytes, i, AgentTextures.Length); i += AgentTextures.Length;
                ActiveGroupID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GroupDataBlock : PacketBlock
        {
            public UUID GroupID;
            public ulong GroupPowers;
            public bool AcceptNotices;

            public override int Length
            {
                get
                {
                    return 25;
                }
            }

            public GroupDataBlock() { }
            public GroupDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GroupID.FromBytes(bytes, i); i += 16;
                    GroupPowers = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    AcceptNotices = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GroupID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(GroupPowers, bytes, i); i += 8;
                bytes[i++] = (byte)((AcceptNotices) ? 1 : 0);
            }

        }

        /// <exclude/>
        public sealed class AnimationDataBlock : PacketBlock
        {
            public UUID Animation;
            public UUID ObjectID;

            public override int Length
            {
                get
                {
                    return 32;
                }
            }

            public AnimationDataBlock() { }
            public AnimationDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Animation.FromBytes(bytes, i); i += 16;
                    ObjectID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Animation.ToBytes(bytes, i); i += 16;
                ObjectID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class GranterBlockBlock : PacketBlock
        {
            public UUID GranterID;

            public override int Length
            {
                get
                {
                    return 16;
                }
            }

            public GranterBlockBlock() { }
            public GranterBlockBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    GranterID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                GranterID.ToBytes(bytes, i); i += 16;
            }

        }

        /// <exclude/>
        public sealed class NVPairDataBlock : PacketBlock
        {
            public byte[] NVPairs;

            public override int Length
            {
                get
                {
                    int length = 2;
                    if (NVPairs != null) { length += NVPairs.Length; }
                    return length;
                }
            }

            public NVPairDataBlock() { }
            public NVPairDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                int length;
                try
                {
                    length = (bytes[i++] + (bytes[i++] << 8));
                    NVPairs = new byte[length];
                    Buffer.BlockCopy(bytes, i, NVPairs, 0, length); i += length;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = (byte)(NVPairs.Length % 256);
                bytes[i++] = (byte)((NVPairs.Length >> 8) % 256);
                Buffer.BlockCopy(NVPairs, 0, bytes, i, NVPairs.Length); i += NVPairs.Length;
            }

        }

        /// <exclude/>
        public sealed class VisualParamBlock : PacketBlock
        {
            public byte ParamValue;

            public override int Length
            {
                get
                {
                    return 1;
                }
            }

            public VisualParamBlock() { }
            public VisualParamBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    ParamValue = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = ParamValue;
            }

        }

        /// <exclude/>
        public sealed class AgentAccessBlock : PacketBlock
        {
            public byte AgentLegacyAccess;
            public byte AgentMaxAccess;

            public override int Length
            {
                get
                {
                    return 2;
                }
            }

            public AgentAccessBlock() { }
            public AgentAccessBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    AgentLegacyAccess = (byte)bytes[i++];
                    AgentMaxAccess = (byte)bytes[i++];
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                bytes[i++] = AgentLegacyAccess;
                bytes[i++] = AgentMaxAccess;
            }

        }

        /// <exclude/>
        public sealed class AgentInfoBlock : PacketBlock
        {
            public uint Flags;

            public override int Length
            {
                get
                {
                    return 4;
                }
            }

            public AgentInfoBlock() { }
            public AgentInfoBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    Flags = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UIntToBytes(Flags, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 14;
                length += AgentData.Length;
                for (int j = 0; j < GroupData.Length; j++)
                    length += GroupData[j].Length;
                for (int j = 0; j < AnimationData.Length; j++)
                    length += AnimationData[j].Length;
                for (int j = 0; j < GranterBlock.Length; j++)
                    length += GranterBlock[j].Length;
                for (int j = 0; j < NVPairData.Length; j++)
                    length += NVPairData[j].Length;
                for (int j = 0; j < VisualParam.Length; j++)
                    length += VisualParam[j].Length;
                for (int j = 0; j < AgentAccess.Length; j++)
                    length += AgentAccess[j].Length;
                for (int j = 0; j < AgentInfo.Length; j++)
                    length += AgentInfo[j].Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;
        public GroupDataBlock[] GroupData;
        public AnimationDataBlock[] AnimationData;
        public GranterBlockBlock[] GranterBlock;
        public NVPairDataBlock[] NVPairData;
        public VisualParamBlock[] VisualParam;
        public AgentAccessBlock[] AgentAccess;
        public AgentInfoBlock[] AgentInfo;

        public ChildAgentUpdatePacket()
        {
            HasVariableBlocks = true;
            Type = PacketType.ChildAgentUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 25;
            Header.Reliable = true;
            Header.Zerocoded = true;
            AgentData = new AgentDataBlock();
            GroupData = null;
            AnimationData = null;
            GranterBlock = null;
            NVPairData = null;
            VisualParam = null;
            AgentAccess = null;
            AgentInfo = null;
        }

        public ChildAgentUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != -1) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AnimationData == null || AnimationData.Length != -1) {
                AnimationData = new AnimationDataBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationData[j] = new AnimationDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(GranterBlock == null || GranterBlock.Length != -1) {
                GranterBlock = new GranterBlockBlock[count];
                for(int j = 0; j < count; j++)
                { GranterBlock[j] = new GranterBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GranterBlock[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(NVPairData == null || NVPairData.Length != -1) {
                NVPairData = new NVPairDataBlock[count];
                for(int j = 0; j < count; j++)
                { NVPairData[j] = new NVPairDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { NVPairData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(VisualParam == null || VisualParam.Length != -1) {
                VisualParam = new VisualParamBlock[count];
                for(int j = 0; j < count; j++)
                { VisualParam[j] = new VisualParamBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VisualParam[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AgentAccess == null || AgentAccess.Length != -1) {
                AgentAccess = new AgentAccessBlock[count];
                for(int j = 0; j < count; j++)
                { AgentAccess[j] = new AgentAccessBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentAccess[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AgentInfo == null || AgentInfo.Length != -1) {
                AgentInfo = new AgentInfoBlock[count];
                for(int j = 0; j < count; j++)
                { AgentInfo[j] = new AgentInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentInfo[j].FromBytes(bytes, ref i); }
        }

        public ChildAgentUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
            int count = (int)bytes[i++];
            if(GroupData == null || GroupData.Length != count) {
                GroupData = new GroupDataBlock[count];
                for(int j = 0; j < count; j++)
                { GroupData[j] = new GroupDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GroupData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AnimationData == null || AnimationData.Length != count) {
                AnimationData = new AnimationDataBlock[count];
                for(int j = 0; j < count; j++)
                { AnimationData[j] = new AnimationDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AnimationData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(GranterBlock == null || GranterBlock.Length != count) {
                GranterBlock = new GranterBlockBlock[count];
                for(int j = 0; j < count; j++)
                { GranterBlock[j] = new GranterBlockBlock(); }
            }
            for (int j = 0; j < count; j++)
            { GranterBlock[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(NVPairData == null || NVPairData.Length != count) {
                NVPairData = new NVPairDataBlock[count];
                for(int j = 0; j < count; j++)
                { NVPairData[j] = new NVPairDataBlock(); }
            }
            for (int j = 0; j < count; j++)
            { NVPairData[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(VisualParam == null || VisualParam.Length != count) {
                VisualParam = new VisualParamBlock[count];
                for(int j = 0; j < count; j++)
                { VisualParam[j] = new VisualParamBlock(); }
            }
            for (int j = 0; j < count; j++)
            { VisualParam[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AgentAccess == null || AgentAccess.Length != count) {
                AgentAccess = new AgentAccessBlock[count];
                for(int j = 0; j < count; j++)
                { AgentAccess[j] = new AgentAccessBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentAccess[j].FromBytes(bytes, ref i); }
            count = (int)bytes[i++];
            if(AgentInfo == null || AgentInfo.Length != count) {
                AgentInfo = new AgentInfoBlock[count];
                for(int j = 0; j < count; j++)
                { AgentInfo[j] = new AgentInfoBlock(); }
            }
            for (int j = 0; j < count; j++)
            { AgentInfo[j].FromBytes(bytes, ref i); }
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            length++;
            for (int j = 0; j < GroupData.Length; j++) { length += GroupData[j].Length; }
            length++;
            for (int j = 0; j < AnimationData.Length; j++) { length += AnimationData[j].Length; }
            length++;
            for (int j = 0; j < GranterBlock.Length; j++) { length += GranterBlock[j].Length; }
            length++;
            for (int j = 0; j < NVPairData.Length; j++) { length += NVPairData[j].Length; }
            length++;
            for (int j = 0; j < VisualParam.Length; j++) { length += VisualParam[j].Length; }
            length++;
            for (int j = 0; j < AgentAccess.Length; j++) { length += AgentAccess[j].Length; }
            length++;
            for (int j = 0; j < AgentInfo.Length; j++) { length += AgentInfo[j].Length; }
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            bytes[i++] = (byte)GroupData.Length;
            for (int j = 0; j < GroupData.Length; j++) { GroupData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)AnimationData.Length;
            for (int j = 0; j < AnimationData.Length; j++) { AnimationData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)GranterBlock.Length;
            for (int j = 0; j < GranterBlock.Length; j++) { GranterBlock[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)NVPairData.Length;
            for (int j = 0; j < NVPairData.Length; j++) { NVPairData[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)VisualParam.Length;
            for (int j = 0; j < VisualParam.Length; j++) { VisualParam[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)AgentAccess.Length;
            for (int j = 0; j < AgentAccess.Length; j++) { AgentAccess[j].ToBytes(bytes, ref i); }
            bytes[i++] = (byte)AgentInfo.Length;
            for (int j = 0; j < AgentInfo.Length; j++) { AgentInfo[j].ToBytes(bytes, ref i); }
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            System.Collections.Generic.List<byte[]> packets = new System.Collections.Generic.List<byte[]>();
            int i = 0;
            int fixedLength = 7;

            byte[] ackBytes = null;
            int acksLength = 0;
            if (Header.AckList != null && Header.AckList.Length > 0) {
                Header.AppendedAcks = true;
                ackBytes = new byte[Header.AckList.Length * 4 + 1];
                Header.AcksToBytes(ackBytes, ref acksLength);
            }

            fixedLength += AgentData.Length;
            byte[] fixedBytes = new byte[fixedLength];
            Header.ToBytes(fixedBytes, ref i);
            AgentData.ToBytes(fixedBytes, ref i);
            fixedLength += 7;

            int GroupDataStart = 0;
            int AnimationDataStart = 0;
            int GranterBlockStart = 0;
            int NVPairDataStart = 0;
            int VisualParamStart = 0;
            int AgentAccessStart = 0;
            int AgentInfoStart = 0;
            do
            {
                int variableLength = 0;
                int GroupDataCount = 0;
                int AnimationDataCount = 0;
                int GranterBlockCount = 0;
                int NVPairDataCount = 0;
                int VisualParamCount = 0;
                int AgentAccessCount = 0;
                int AgentInfoCount = 0;

                i = GroupDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < GroupData.Length) {
                    int blockLength = GroupData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++GroupDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = AnimationDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AnimationData.Length) {
                    int blockLength = AnimationData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AnimationDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = GranterBlockStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < GranterBlock.Length) {
                    int blockLength = GranterBlock[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++GranterBlockCount;
                    }
                    else { break; }
                    ++i;
                }

                i = NVPairDataStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < NVPairData.Length) {
                    int blockLength = NVPairData[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++NVPairDataCount;
                    }
                    else { break; }
                    ++i;
                }

                i = VisualParamStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < VisualParam.Length) {
                    int blockLength = VisualParam[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++VisualParamCount;
                    }
                    else { break; }
                    ++i;
                }

                i = AgentAccessStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AgentAccess.Length) {
                    int blockLength = AgentAccess[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AgentAccessCount;
                    }
                    else { break; }
                    ++i;
                }

                i = AgentInfoStart;
                while (fixedLength + variableLength + acksLength < Packet.MTU && i < AgentInfo.Length) {
                    int blockLength = AgentInfo[i].Length;
                    if (fixedLength + variableLength + blockLength + acksLength <= MTU) {
                        variableLength += blockLength;
                        ++AgentInfoCount;
                    }
                    else { break; }
                    ++i;
                }

                byte[] packet = new byte[fixedLength + variableLength + acksLength];
                int length = fixedBytes.Length;
                Buffer.BlockCopy(fixedBytes, 0, packet, 0, length);
                if (packets.Count > 0) { packet[0] = (byte)(packet[0] & ~0x10); }

                packet[length++] = (byte)GroupDataCount;
                for (i = GroupDataStart; i < GroupDataStart + GroupDataCount; i++) { GroupData[i].ToBytes(packet, ref length); }
                GroupDataStart += GroupDataCount;

                packet[length++] = (byte)AnimationDataCount;
                for (i = AnimationDataStart; i < AnimationDataStart + AnimationDataCount; i++) { AnimationData[i].ToBytes(packet, ref length); }
                AnimationDataStart += AnimationDataCount;

                packet[length++] = (byte)GranterBlockCount;
                for (i = GranterBlockStart; i < GranterBlockStart + GranterBlockCount; i++) { GranterBlock[i].ToBytes(packet, ref length); }
                GranterBlockStart += GranterBlockCount;

                packet[length++] = (byte)NVPairDataCount;
                for (i = NVPairDataStart; i < NVPairDataStart + NVPairDataCount; i++) { NVPairData[i].ToBytes(packet, ref length); }
                NVPairDataStart += NVPairDataCount;

                packet[length++] = (byte)VisualParamCount;
                for (i = VisualParamStart; i < VisualParamStart + VisualParamCount; i++) { VisualParam[i].ToBytes(packet, ref length); }
                VisualParamStart += VisualParamCount;

                packet[length++] = (byte)AgentAccessCount;
                for (i = AgentAccessStart; i < AgentAccessStart + AgentAccessCount; i++) { AgentAccess[i].ToBytes(packet, ref length); }
                AgentAccessStart += AgentAccessCount;

                packet[length++] = (byte)AgentInfoCount;
                for (i = AgentInfoStart; i < AgentInfoStart + AgentInfoCount; i++) { AgentInfo[i].ToBytes(packet, ref length); }
                AgentInfoStart += AgentInfoCount;

                if (acksLength > 0) {
                    Buffer.BlockCopy(ackBytes, 0, packet, length, acksLength);
                    acksLength = 0;
                }

                packets.Add(packet);
            } while (
                GroupDataStart < GroupData.Length ||
                AnimationDataStart < AnimationData.Length ||
                GranterBlockStart < GranterBlock.Length ||
                NVPairDataStart < NVPairData.Length ||
                VisualParamStart < VisualParam.Length ||
                AgentAccessStart < AgentAccess.Length ||
                AgentInfoStart < AgentInfo.Length);

            return packets.ToArray();
        }
    }

    /// <exclude/>
    public sealed class ChildAgentAlivePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public uint ViewerCircuitCode;
            public UUID AgentID;
            public UUID SessionID;

            public override int Length
            {
                get
                {
                    return 44;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    ViewerCircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                Utils.UIntToBytes(ViewerCircuitCode, bytes, i); i += 4;
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ChildAgentAlivePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ChildAgentAlive;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 26;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public ChildAgentAlivePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ChildAgentAlivePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class ChildAgentPositionUpdatePacket : Packet
    {
        /// <exclude/>
        public sealed class AgentDataBlock : PacketBlock
        {
            public ulong RegionHandle;
            public uint ViewerCircuitCode;
            public UUID AgentID;
            public UUID SessionID;
            public Vector3 AgentPos;
            public Vector3 AgentVel;
            public Vector3 Center;
            public Vector3 Size;
            public Vector3 AtAxis;
            public Vector3 LeftAxis;
            public Vector3 UpAxis;
            public bool ChangedGrid;

            public override int Length
            {
                get
                {
                    return 129;
                }
            }

            public AgentDataBlock() { }
            public AgentDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    RegionHandle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    ViewerCircuitCode = (uint)(bytes[i++] + (bytes[i++] << 8) + (bytes[i++] << 16) + (bytes[i++] << 24));
                    AgentID.FromBytes(bytes, i); i += 16;
                    SessionID.FromBytes(bytes, i); i += 16;
                    AgentPos.FromBytes(bytes, i); i += 12;
                    AgentVel.FromBytes(bytes, i); i += 12;
                    Center.FromBytes(bytes, i); i += 12;
                    Size.FromBytes(bytes, i); i += 12;
                    AtAxis.FromBytes(bytes, i); i += 12;
                    LeftAxis.FromBytes(bytes, i); i += 12;
                    UpAxis.FromBytes(bytes, i); i += 12;
                    ChangedGrid = (bytes[i++] != 0) ? (bool)true : (bool)false;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                Utils.UInt64ToBytes(RegionHandle, bytes, i); i += 8;
                Utils.UIntToBytes(ViewerCircuitCode, bytes, i); i += 4;
                AgentID.ToBytes(bytes, i); i += 16;
                SessionID.ToBytes(bytes, i); i += 16;
                AgentPos.ToBytes(bytes, i); i += 12;
                AgentVel.ToBytes(bytes, i); i += 12;
                Center.ToBytes(bytes, i); i += 12;
                Size.ToBytes(bytes, i); i += 12;
                AtAxis.ToBytes(bytes, i); i += 12;
                LeftAxis.ToBytes(bytes, i); i += 12;
                UpAxis.ToBytes(bytes, i); i += 12;
                bytes[i++] = (byte)((ChangedGrid) ? 1 : 0);
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += AgentData.Length;
                return length;
            }
        }
        public AgentDataBlock AgentData;

        public ChildAgentPositionUpdatePacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.ChildAgentPositionUpdate;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 27;
            Header.Reliable = true;
            AgentData = new AgentDataBlock();
        }

        public ChildAgentPositionUpdatePacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            AgentData.FromBytes(bytes, ref i);
        }

        public ChildAgentPositionUpdatePacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            AgentData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += AgentData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            AgentData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

    /// <exclude/>
    public sealed class SoundTriggerPacket : Packet
    {
        /// <exclude/>
        public sealed class SoundDataBlock : PacketBlock
        {
            public UUID SoundID;
            public UUID OwnerID;
            public UUID ObjectID;
            public UUID ParentID;
            public ulong Handle;
            public Vector3 Position;
            public float Gain;

            public override int Length
            {
                get
                {
                    return 88;
                }
            }

            public SoundDataBlock() { }
            public SoundDataBlock(byte[] bytes, ref int i)
            {
                FromBytes(bytes, ref i);
            }

            public override void FromBytes(byte[] bytes, ref int i)
            {
                try
                {
                    SoundID.FromBytes(bytes, i); i += 16;
                    OwnerID.FromBytes(bytes, i); i += 16;
                    ObjectID.FromBytes(bytes, i); i += 16;
                    ParentID.FromBytes(bytes, i); i += 16;
                    Handle = (ulong)((ulong)bytes[i++] + ((ulong)bytes[i++] << 8) + ((ulong)bytes[i++] << 16) + ((ulong)bytes[i++] << 24) + ((ulong)bytes[i++] << 32) + ((ulong)bytes[i++] << 40) + ((ulong)bytes[i++] << 48) + ((ulong)bytes[i++] << 56));
                    Position.FromBytes(bytes, i); i += 12;
                    Gain = Utils.BytesToFloat(bytes, i); i += 4;
                }
                catch (Exception)
                {
                    throw new MalformedDataException();
                }
            }

            public override void ToBytes(byte[] bytes, ref int i)
            {
                SoundID.ToBytes(bytes, i); i += 16;
                OwnerID.ToBytes(bytes, i); i += 16;
                ObjectID.ToBytes(bytes, i); i += 16;
                ParentID.ToBytes(bytes, i); i += 16;
                Utils.UInt64ToBytes(Handle, bytes, i); i += 8;
                Position.ToBytes(bytes, i); i += 12;
                Utils.FloatToBytes(Gain, bytes, i); i += 4;
            }

        }

        public override int Length
        {
            get
            {
                int length = 7;
                length += SoundData.Length;
                return length;
            }
        }
        public SoundDataBlock SoundData;

        public SoundTriggerPacket()
        {
            HasVariableBlocks = false;
            Type = PacketType.SoundTrigger;
            Header = new Header();
            Header.Frequency = PacketFrequency.High;
            Header.ID = 29;
            Header.Reliable = true;
            SoundData = new SoundDataBlock();
        }

        public SoundTriggerPacket(byte[] bytes, ref int i) : this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(bytes, ref i, ref packetEnd, null);
        }

        override public void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
        {
            Header.FromBytes(bytes, ref i, ref packetEnd);
            if (Header.Zerocoded && zeroBuffer != null)
            {
                packetEnd = Helpers.ZeroDecode(bytes, packetEnd + 1, zeroBuffer) - 1;
                bytes = zeroBuffer;
            }
            SoundData.FromBytes(bytes, ref i);
        }

        public SoundTriggerPacket(Header head, byte[] bytes, ref int i): this()
        {
            int packetEnd = bytes.Length - 1;
            FromBytes(head, bytes, ref i, ref packetEnd);
        }

        override public void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd)
        {
            Header = header;
            SoundData.FromBytes(bytes, ref i);
        }

        public override byte[] ToBytes()
        {
            int length = 7;
            length += SoundData.Length;
            if (Header.AckList != null && Header.AckList.Length > 0) { length += Header.AckList.Length * 4 + 1; }
            byte[] bytes = new byte[length];
            int i = 0;
            Header.ToBytes(bytes, ref i);
            SoundData.ToBytes(bytes, ref i);
            if (Header.AckList != null && Header.AckList.Length > 0) { Header.AcksToBytes(bytes, ref i); }
            return bytes;
        }

        public override byte[][] ToBytesMultiple()
        {
            return new byte[][] { ToBytes() };
        }
    }

}