public PrimVisualCylinder(PrimObject prim)
            : base(prim)
        {
            NumberFaces = 1;
            FirstOuterFace = 0;
            LastOuterFace = 0;

            OuterFaces = new CrossSection[1];
            OuterFaces[0] = new CrossSection();

            if (prim.ProfileHollow != 0)
            {
                hollow = true;
                InnerFaces = new CrossSection[1];
                InnerFaces[0] = new CrossSection();

                //for (int i = 0; i < 4; i++)
                //{
                //    InnerFaces[i] = new CrossSection();
                //}
            }

            if (prim.ProfileBegin != 0 || prim.ProfileEnd != 1)
            {
                cut = true;
                CutFaces = new CrossSection[2];
                for (int i = 0; i < 2; i++)
                {
                    CutFaces[i] = new CrossSection();
                }
            }

            BuildFaces();
        }
Exemple #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="prim"></param>
        /// <param name="position"></param>
        /// <param name="avatarPosition"></param>
        public void RezObject(PrimObject prim, LLVector3 position, LLVector3 rayStart,
                              LLUUID groupID)
        {
            ObjectAddPacket add = new ObjectAddPacket();

            add.AgentData.AgentID   = Client.Network.AgentID;
            add.AgentData.SessionID = Client.Network.SessionID;
            add.AgentData.GroupID   = groupID;
            // TODO: Why 2?
            add.ObjectData.AddFlags             = 2;
            add.ObjectData.BypassRaycast        = 1;
            add.ObjectData.Material             = (byte)prim.Material;
            add.ObjectData.PathBegin            = PrimObject.PathBeginByte(prim.PathBegin);
            add.ObjectData.PathCurve            = (byte)prim.PathCurve;
            add.ObjectData.PathEnd              = PrimObject.PathEndByte(prim.PathEnd);
            add.ObjectData.PathRadiusOffset     = PrimObject.PathRadiusOffsetByte(prim.PathRadiusOffset);
            add.ObjectData.PathRevolutions      = PrimObject.PathRevolutionsByte(prim.PathRevolutions);
            add.ObjectData.PathScaleX           = PrimObject.PathScaleByte(prim.PathScaleX);
            add.ObjectData.PathScaleY           = PrimObject.PathScaleByte(prim.PathScaleY);
            add.ObjectData.PathShearX           = PrimObject.PathShearByte(prim.PathShearX);
            add.ObjectData.PathShearY           = PrimObject.PathShearByte(prim.PathShearY);
            add.ObjectData.PathSkew             = PrimObject.PathSkewByte(prim.PathSkew);
            add.ObjectData.PathTaperX           = PrimObject.PathTaperByte(prim.PathTaperX);
            add.ObjectData.PathTaperY           = PrimObject.PathTaperByte(prim.PathTaperY);
            add.ObjectData.PathTwist            = PrimObject.PathTwistByte(prim.PathTwist);
            add.ObjectData.PathTwistBegin       = PrimObject.PathTwistByte(prim.PathTwistBegin);
            add.ObjectData.PCode                = (byte)prim.PCode;
            add.ObjectData.ProfileBegin         = PrimObject.ProfileBeginByte(prim.ProfileBegin);
            add.ObjectData.ProfileCurve         = (byte)prim.ProfileCurve;
            add.ObjectData.ProfileEnd           = PrimObject.ProfileEndByte(prim.ProfileEnd);
            add.ObjectData.ProfileHollow        = (byte)prim.ProfileHollow;
            add.ObjectData.RayEnd               = position;
            add.ObjectData.RayEndIsIntersection = 0;
            add.ObjectData.RayStart             = rayStart;
            add.ObjectData.RayTargetID          = LLUUID.GenerateUUID();
            add.ObjectData.Rotation             = prim.Rotation;
            add.ObjectData.Scale                = prim.Scale;
            add.ObjectData.State                = (byte)prim.State;
            if (prim.Textures != null)
            {
                add.ObjectData.TextureEntry = prim.Textures.ToBytes();
            }
            else
            {
                add.ObjectData.TextureEntry = new byte[0];
            }

            Client.Network.SendPacket(add);
        }
        public PrimVisual(PrimObject prim)
        {
            Prim = prim;
            Vertexes = new List<VertexPositionColor>();
            VertexArray = Vertexes.ToArray();

            Acceleration = Vector3.Zero;
            Velocity = Vector3.Zero;
            RotationVelocity = Vector3.Zero;

            // TODO: This is temporary, for debugging and entertainment purposes
            Random rand = new Random((int)Prim.LocalID + Environment.TickCount);
            byte r = (byte)rand.Next(256);
            byte g = (byte)rand.Next(256);
            byte b = (byte)rand.Next(256);
            color = new Color(r, g, b);

            BuildMatrix();
        }
        public PrimVisualBox(PrimObject prim)
            : base(prim)
        {
            NumberFaces = 4;
            FirstOuterFace = 0;
            LastOuterFace = 3;

            ReferenceVertices = new Vector3[4];

            ReferenceVertices[1] = new Vector3(0.5f, -0.5f, 0f);
            ReferenceVertices[2] = new Vector3(0.5f, 0.5f, 0f);
            ReferenceVertices[3] = new Vector3(-0.5f, 0.5f, 0f);
            ReferenceVertices[0] = new Vector3(-0.5f, -0.5f, 0f);

            OuterFaces = new CrossSection[4];
            for (int i = 0; i < 4; i++)
            {
                OuterFaces[i] = new CrossSection();
            }

            if (prim.ProfileHollow != 0)
            {
                hollow = true;
                InnerFaces = new CrossSection[4];
                for (int i = 0; i < 4; i++)
                {
                    InnerFaces[i] = new CrossSection();
                }
            }

            if (prim.ProfileBegin != 0 || prim.ProfileEnd != 1)
            {
                cut = true;
                CutFaces = new CrossSection[2];
                for (int i = 0; i < 2; i++)
                {
                    CutFaces[i] = new CrossSection();
                }
            }

            BuildFaces();
        }
 public PrimVisualTube(PrimObject prim)
     : base(prim)
 {
     ;
 }
        void TestClient_OnPrimCreated(Simulator simulator, PrimObject prim)
        {
            if (rezzingRootPrim)
            {
                rootLocalID = prim.LocalID;
            }

            if (!linking)
            {
                Console.WriteLine("Setting properties for " + prim.LocalID);

                primsCreated.Add(prim);

                // FIXME: Replace these individual calls with a single ObjectUpdate that sets the
                // particle system and everything
                currentClient.Objects.SetPosition(simulator, prim.LocalID, currentPosition);
                currentClient.Objects.SetTextures(simulator, prim.LocalID, currentPrim.Textures);
                //currentClient.Objects.SetLight(simulator, prim.LocalID, currentPrim.Light);
                //currentClient.Objects.SetFlexible(simulator, prim.LocalID, currentPrim.Flexible);
            }

            primDone.Set();
        }
        private void UpdateHandler(Packet packet, Simulator simulator)
        {
            if (OnNewPrim != null || OnNewAttachment != null || OnNewAvatar != null || OnNewFoliage != null)
            {
                ObjectUpdatePacket update = (ObjectUpdatePacket)packet;

                foreach (ObjectUpdatePacket.ObjectDataBlock block in update.ObjectData)
                {
                    byte pcode = block.PCode;
                    switch (pcode)
                    {
                        case (byte)PCode.Grass:
                        case (byte)PCode.Tree:
                        case (byte)PCode.Prim:
                            string name = Helpers.FieldToString(block.NameValue);

                            // New prim spotted
                            PrimObject prim = new PrimObject();

                            prim.Name = name;

							prim.RegionHandle = update.RegionData.RegionHandle;
                            prim.Position = new LLVector3(block.ObjectData, 0);
                            prim.Rotation = new LLQuaternion(block.ObjectData, 36, true);
                            // TODO: Parse the rest of the ObjectData byte array fields

                            prim.LocalID = block.ID;
                            prim.State = block.State;
                            prim.ID = block.FullID;
                            prim.ParentID = block.ParentID;
                            //block.OwnerID Sound-related
                            prim.Material = block.Material;
                            prim.PathCurve = block.PathCurve;
                            prim.ProfileCurve = block.ProfileCurve;
                            prim.PathBegin = PrimObject.PathBeginFloat(block.PathBegin);
                            prim.PathEnd = PrimObject.PathEndFloat(block.PathEnd);
                            prim.PathScaleX = PrimObject.PathScaleFloat(block.PathScaleX);
                            prim.PathScaleY = PrimObject.PathScaleFloat(block.PathScaleY);
                            prim.PathShearX = PrimObject.PathShearFloat(block.PathShearX);
                            prim.PathShearY = PrimObject.PathShearFloat(block.PathShearY);
                            prim.PathTwist = block.PathTwist;
                            prim.PathTwistBegin = block.PathTwistBegin;
                            prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat(block.PathRadiusOffset);
                            prim.PathTaperX = PrimObject.PathTaperFloat(block.PathTaperX);
                            prim.PathTaperY = PrimObject.PathTaperFloat(block.PathTaperY);
                            prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.PathRevolutions);
                            prim.PathSkew = PrimObject.PathSkewFloat(block.PathSkew);
                            prim.ProfileBegin = PrimObject.ProfileBeginFloat(block.ProfileBegin);
                            prim.ProfileEnd = PrimObject.ProfileEndFloat(block.ProfileEnd);
                            prim.ProfileHollow = block.ProfileHollow;


                            //block.Data ?
                            prim.Text = ASCIIEncoding.ASCII.GetString(block.Text);
                            //block.TextColor LLColor4U of the hovering text
                            //block.MediaURL Quicktime stream
                            prim.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length);
                            prim.TextureAnim = new TextureAnimation(block.TextureAnim, 0);
                            //block.JointType ?
                            //block.JointPivot ?
                            //block.JointAxisOrAnchor ?
                            prim.ParticleSys = new ParticleSystem(block.PSBlock, 0);
                            prim.SetExtraParamsFromBytes(block.ExtraParams, 0);
                            prim.Scale = block.Scale;
                            //block.Flags ?
                            prim.Flags = (ObjectFlags)block.UpdateFlags;
                            //block.ClickAction ?
                            //block.Gain Sound-related
                            //block.Sound Sound-related
                            //block.Radius Sound-related

                            if (prim.Name.StartsWith("AttachItemID"))
                            {
                                if (OnNewAttachment != null)
                                {
                                    OnNewAttachment(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                            else if (block.PCode == (byte)PCode.Tree || block.PCode == (byte)PCode.Grass)
                            {
                                if (OnNewFoliage != null)
                                {
                                    OnNewFoliage(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                            else if (OnNewPrim != null)
                            {
                                OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                            }

                            break;
                        case (byte)PCode.Avatar:
                            // Update some internals if this is our avatar
                            if (block.FullID == Client.Network.AgentID)
                            {
                                // Update our current position information
                                Client.Self.LocalID = block.ID;
                                //avatar.CollisionPlane = new LLQuaternion(block.ObjectData, 0);
                                Client.Self.Position = new LLVector3(block.ObjectData, 16);
                                Client.Self.Rotation = new LLQuaternion(block.ObjectData, 52, true);
                                // TODO: Parse the rest of the ObjectData byte array fields

                                // Detect if we are sitting or standing
                                uint oldSittingOn = Client.Self.sittingOn;
                                Client.Self.sittingOn = block.ParentID;

                                // Fire the callback for our sitting orientation changing
                                if (Client.Self.sittingOn != oldSittingOn && OnAvatarSitChanged != null)
                                {
                                    OnAvatarSitChanged(simulator, Client.Self.sittingOn);
                                }
                            }

                            if (OnNewAvatar != null)
                            {
                                Avatar avatar = new Avatar();

                                string FirstName = "";
                                string LastName = "";
                                string GroupName = "";

                                //avatar.CollisionPlane = new LLQuaternion(block.ObjectData, 0);
                                avatar.Position = new LLVector3(block.ObjectData, 16);
                                avatar.Rotation = new LLQuaternion(block.ObjectData, 52, true);
                                // TODO: Parse the rest of the ObjectData byte array fields

                                avatar.sittingOn = block.ParentID;

                                ParseAvName(Helpers.FieldToString(block.NameValue), ref FirstName, ref LastName, ref GroupName);

                                avatar.ID = block.FullID;
                                avatar.LocalID = block.ID;
                                avatar.Name = FirstName + " " + LastName;
                                avatar.GroupName = GroupName;
                                avatar.Online = true;
                                avatar.CurrentRegion = simulator.Region;

                                avatar.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length);

                                if (OnNewAvatar != null)
                                {
                                    OnNewAvatar(simulator, avatar, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                            break;
                        case (byte)PCode.ParticleSystem:
                            // FIXME: Handle ParticleSystem
                            Client.DebugLog("Got an ObjectUpdate block with a ParticleSystem PCode");
                            break;
                        default:
                            break;
                    }
                }
            }
        }
#pragma warning disable 0219 // disable "value assigned but never used" while this function is incomplete

        private void CompressedUpdateHandler(Packet packet, Simulator simulator)
        {
            if (OnNewPrim != null || OnNewAvatar != null || OnNewAttachment != null || OnNewFoliage != null)
            {
                ObjectUpdateCompressedPacket update = (ObjectUpdateCompressedPacket)packet;
                PrimObject prim;

                foreach (ObjectUpdateCompressedPacket.ObjectDataBlock block in update.ObjectData)
                {
                    int i = 0;
                    prim = new PrimObject();

                    prim.Flags = (ObjectFlags)block.UpdateFlags;

                    try
                    {
                        prim.ID = new LLUUID(block.Data, 0);
                        i += 16;
                        prim.LocalID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                            (block.Data[i++] << 16) + (block.Data[i++] << 24));

                        byte pcode = block.Data[i++];
                        if (pcode == (byte)PCode.Prim)
                        {
                            #region Prim
                            prim.State = (uint)block.Data[i++];
                            i += 4; // CRC
                            prim.Material = (uint)block.Data[i++];
                            i++; // TODO: ClickAction

                            prim.Scale = new LLVector3(block.Data, i);
                            i += 12;
                            prim.Position = new LLVector3(block.Data, i);
                            i += 12;
                            prim.Rotation = new LLQuaternion(block.Data, i, true);
                            i += 12;

                            int flagsValue = (int)block.Data[i++] + (int)(block.Data[i++] << 8) +
                                (int)(block.Data[i++] << 16) + (int)(block.Data[i++] << 24);
                            CompressedFlags flags = (CompressedFlags)flagsValue;

                            if ((flags & CompressedFlags.Tree) != 0)
                            {
                                // FIXME: I don't think this is even Tree data, as it would have
                                // a different PCode. Figure out what this flag is and how to 
                                // decode it
                                byte Unknown1 = block.Data[i++];
                                byte Unknown2 = block.Data[i++];

                                Client.DebugLog("Compressed object with Tree flag set: " + Environment.NewLine +
                                    "Unknown byte 1: " + Unknown1 + Environment.NewLine + "Unknown byte 2: " + Unknown2);
                            }

                            if ((flags & CompressedFlags.HasParent) != 0)
                            {
                                prim.ParentID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                                (block.Data[i++] << 16) + (block.Data[i++] << 24));
                            }
                            else
                            {
                                prim.ParentID = 0;
                            }

                            if ((flags & CompressedFlags.HasAngularVelocity) != 0)
                            {
                                // TODO: Use this
                                LLVector3 Omega = new LLVector3(block.Data, i);
                                i += 12;
                            }

                            if ((flags & CompressedFlags.HasText) != 0)
                            {
                                string text = "";
                                while (block.Data[i] != 0)
                                {
                                    text += (char)block.Data[i];
                                    i++;
                                }
                                i++;

                                prim.Text = text;

                                // TODO: Text color
                                i += 4;
                            }
                            else
                            {
                                prim.Text = "";
                            }

                            if ((flags & CompressedFlags.HasParticles) != 0)
                            {
                                prim.ParticleSys = new ParticleSystem(block.Data, i);
                                i += 86;
                            }

                            i += prim.SetExtraParamsFromBytes(block.Data, i);

                            //Sound data
                            if ((flags & CompressedFlags.HasSound) != 0)
                            {
                                //TODO: use this data
                                LLUUID SoundUUID = new LLUUID(block.Data, i);
                                i += 16;
                                LLUUID OwnerUUID = new LLUUID(block.Data, i);
                                i += 16;

                                if (!BitConverter.IsLittleEndian)
                                {
                                    Array.Reverse(block.Data, i, 4);
                                    Array.Reverse(block.Data, i + 5, 4);
                                }

                                float SoundGain = BitConverter.ToSingle(block.Data, i);
                                i += 4;
                                byte SoundFlags = block.Data[i++];
                                float SoundRadius = BitConverter.ToSingle(block.Data, i);
                                i += 4;
                            }

                            // Indicates that this is an attachment
                            if ((flags & CompressedFlags.Attachment) != 0)
                            {
                                // Get the attachment string
                                // Example: "AttachItemID STRING RW SV fa9a5ab8-1bad-b449-9873-cf5b803e664e"
                                string text = "";
                                while (block.Data[i] != 0)
                                {
                                    text += (char)block.Data[i];
                                    i++;
                                }
                                i++;

                                prim.Name = text;
                            }
                            else
                            {
                                prim.Name = "";
                            }

                            if ((flags & CompressedFlags.Unknown1) != 0)
                            {
                                // TODO: Is this even a valid flag?
                                Client.DebugLog("Compressed object with Unknown1 flag set: " + Environment.NewLine +
                                    "Flags: " + flags.ToString() + Environment.NewLine +
                                    Helpers.FieldToString(block.Data));
                            }

                            if ((flags & CompressedFlags.Unknown2) != 0)
                            {
                                // FIXME: Implement CompressedFlags.Unknown2
                                //Client.DebugLog("Compressed object with Unknown2 flag set: " + Environment.NewLine +
                                //    "Flags: " + flags.ToString() + Environment.NewLine +
                                //    Helpers.FieldToString(block.Data));
                            }

                            prim.PathCurve = (uint)block.Data[i++];
                            prim.PathBegin = PrimObject.PathBeginFloat(block.Data[i++]);
                            prim.PathEnd = PrimObject.PathEndFloat(block.Data[i++]);
                            prim.PathScaleX = PrimObject.PathScaleFloat(block.Data[i++]);
                            prim.PathScaleY = PrimObject.PathScaleFloat(block.Data[i++]);
                            prim.PathShearX = PrimObject.PathShearFloat(block.Data[i++]);
                            prim.PathShearY = PrimObject.PathShearFloat(block.Data[i++]);
                            prim.PathTwist = (int)block.Data[i++];
                            prim.PathTwistBegin = (int)block.Data[i++];
                            prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat((sbyte)block.Data[i++]);
                            prim.PathTaperX = PrimObject.PathTaperFloat((sbyte)block.Data[i++]);
                            prim.PathTaperY = PrimObject.PathTaperFloat((sbyte)block.Data[i++]);
                            prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.Data[i++]);
                            prim.PathSkew = PrimObject.PathSkewFloat((sbyte)block.Data[i++]);

                            prim.ProfileCurve = (uint)block.Data[i++];
                            prim.ProfileBegin = PrimObject.ProfileBeginFloat(block.Data[i++]);
                            prim.ProfileEnd = PrimObject.ProfileEndFloat(block.Data[i++]);
                            prim.ProfileHollow = (uint)block.Data[i++];

                            int textureEntryLength = (int)(block.Data[i++] + (block.Data[i++] << 8) +
                                (block.Data[i++] << 16) + (block.Data[i++] << 24));

                            prim.Textures = new TextureEntry(block.Data, i, textureEntryLength);

                            i += textureEntryLength;

                            // Assume everything else is texture animation data
                            if (i < block.Data.Length)
                            {
                                int textureAnimLength = (int)(block.Data[i++] + (block.Data[i++] << 8) +
                                    (block.Data[i++] << 16) + (block.Data[i++] << 24));

                                prim.TextureAnim = new TextureAnimation(block.Data, i);
                            }

                            // Fire the appropriate callback
                            if ((flags & CompressedFlags.Attachment) != 0)
                            {
                                if (OnNewAttachment != null)
                                {
                                    OnNewAttachment(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                            else if ((flags & CompressedFlags.Tree) != 0)
                            {
                                if (OnNewFoliage != null)
                                {
                                    OnNewFoliage(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                            else if (OnNewPrim != null)
                            {
                                OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                            }
                            #endregion Prim
                        }
                        else if (pcode == (byte)PCode.Grass || pcode == (byte)PCode.Tree || pcode == (byte)PCode.NewTree)
                        {
                            // FIXME: Implement this
                            //Client.DebugLog("######### Got an ObjectUpdateCompressed for grass/tree, implement this! #########");
                        }
                        else
                        {
                            Client.Log("######### Got an ObjectUpdateCompressed for PCode=" + pcode.ToString() + 
                                ", implement this! #########", Helpers.LogLevel.Debug);
                        }
                    }
                    catch (System.IndexOutOfRangeException e)
                    {
                        Client.Log("Had a problem decoding an ObjectUpdateCompressed packet: " +
                            e.ToString(), Helpers.LogLevel.Warning);
                        Client.Log(block.ToString(), Helpers.LogLevel.Warning);
                    }
                }
            }
        }
        private void CompressedUpdateHandler(Packet packet, Simulator simulator)
        {
            ObjectUpdateCompressedPacket update = (ObjectUpdateCompressedPacket)packet;
            PrimObject prim;

            foreach (ObjectUpdateCompressedPacket.ObjectDataBlock block in update.ObjectData)
            {
                int i = 0;
                prim = new PrimObject(Client);

                try
                {
                    prim.ID      = new LLUUID(block.Data, 0);
                    i           += 16;
                    prim.LocalID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                                          (block.Data[i++] << 16) + (block.Data[i++] << 24));

                    byte pcode = block.Data[i++];

                    if (pcode == (byte)PCode.Prim)
                    {
                        #region PrimRegion
                        prim.State    = (uint)block.Data[i++];
                        i            += 4; // CRC
                        prim.Material = (uint)block.Data[i++];
                        i++;               // TODO: ClickAction

                        prim.Scale    = new LLVector3(block.Data, i);
                        i            += 12;
                        prim.Position = new LLVector3(block.Data, i);
                        i            += 12;
                        prim.Rotation = new LLQuaternion(block.Data, i, true);
                        i            += 12;

                        uint flags = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                                            (block.Data[i++] << 16) + (block.Data[i++] << 24));

                        if ((flags & 0x02) != 0)
                        {
                            byte TreeData = block.Data[i++];

                            // TODO: Unknown byte
                            i++;

                            if (OnNewPrim != null)
                            {
                                OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                            }
                            continue;
                        }

                        if ((flags & 0x20) != 0)
                        {
                            prim.ParentID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                                                   (block.Data[i++] << 16) + (block.Data[i++] << 24));
                        }
                        else
                        {
                            prim.ParentID = 0;
                        }

                        if ((flags & 0x80) != 0)
                        {
                            // TODO: Use this. What is it?
                            LLVector3 Omega = new LLVector3(block.Data, i);
                            i += 12;
                        }

                        if ((flags & 0x04) != 0)
                        {
                            string text = "";
                            while (block.Data[i] != 0)
                            {
                                text += (char)block.Data[i];
                                i++;
                            }
                            prim.Text = text;
                            i++;

                            // Text color
                            i += 4;
                        }
                        else
                        {
                            prim.Text = "";
                        }

                        if ((flags & 0x08) != 0)
                        {
                            prim.ParticleSys = new ParticleSystem(block.Data, i);
                            i += 86;
                        }

                        i += prim.SetExtraParamsFromBytes(block.Data, i);

                        //Sound data
                        if ((flags & 0x10) != 0)
                        {
                            //TODO: use this data
                            LLUUID SoundUUID = new LLUUID(block.Data, i);
                            i += 16;
                            LLUUID OwnerUUID = new LLUUID(block.Data, i);
                            i += 16;

                            if (!BitConverter.IsLittleEndian)
                            {
                                Array.Reverse(block.Data, i, 4);
                                Array.Reverse(block.Data, i + 5, 4);
                            }

                            float SoundGain = BitConverter.ToSingle(block.Data, i);
                            i += 4;
                            byte  SoundFlags  = block.Data[i++];
                            float SoundRadius = BitConverter.ToSingle(block.Data, i);
                            i += 4;
                        }

                        //Indicates that this is an attachment?
                        if ((flags & 0x100) != 0)
                        {
                            //A string
                            //Example: "AttachItemID STRING RW SV fa9a5ab8-1bad-b449-9873-cf5b803e664e"
                            while (block.Data[i] != 0)
                            {
                                i++;
                            }
                            i++;
                        }

                        prim.PathCurve        = (uint)block.Data[i++];
                        prim.PathBegin        = PrimObject.PathBeginFloat(block.Data[i++]);
                        prim.PathEnd          = PrimObject.PathEndFloat(block.Data[i++]);
                        prim.PathTaperX       = PrimObject.PathScaleFloat(block.Data[i++]);
                        prim.PathTaperY       = PrimObject.PathScaleFloat(block.Data[i++]);
                        prim.PathShearX       = PrimObject.PathShearFloat(block.Data[i++]);
                        prim.PathShearY       = PrimObject.PathShearFloat(block.Data[i++]);
                        prim.PathTwist        = (int)block.Data[i++];
                        prim.PathTwistBegin   = (int)block.Data[i++];
                        prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat((sbyte)block.Data[i++]);
                        //prim.PathTaperX = PrimObject.PathTaperFloat(block.Data[i++]);
                        //prim.PathTaperY = PrimObject.PathTaperFloat(block.Data[i++]);
                        i += 2;
                        prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.Data[i++]);
                        prim.PathSkew        = PrimObject.PathSkewFloat(block.Data[i++]);

                        prim.ProfileCurve  = (uint)block.Data[i++];
                        prim.ProfileBegin  = PrimObject.ProfileBeginFloat(block.Data[i++]);
                        prim.ProfileEnd    = PrimObject.ProfileEndFloat(block.Data[i++]);
                        prim.ProfileHollow = (uint)block.Data[i++];

                        int textureEntryLength = (int)(block.Data[i++] + (block.Data[i++] << 8) +
                                                       (block.Data[i++] << 16) + (block.Data[i++] << 24));

                        prim.Textures = new TextureEntry(block.Data, i, textureEntryLength);

                        i += textureEntryLength;

                        if (i < block.Data.Length)
                        {
                            int textureAnimLength = (int)(block.Data[i++] + (block.Data[i++] << 8) +
                                                          (block.Data[i++] << 16) + (block.Data[i++] << 24));

                            prim.TextureAnim = new TextureAnimation(block.Data, i);
                        }

                        if (OnNewPrim != null)
                        {
                            OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                        }

                        #endregion PrimRegion
                    }
                    else if (pcode == (byte)PCode.Avatar)
                    {
                        Client.Log("######### Got an ObjectUpdateCompressed for an avatar, implement this! #########",
                                   Helpers.LogLevel.Warning);
                    }
                    else if (pcode == (byte)PCode.Grass || pcode == (byte)PCode.Tree)
                    {
                        // TODO: Add new_tree and any other tree-like prims
                        ;
                    }
                    else
                    {
                        // TODO: ...
                        continue;
                    }
                }
                catch (System.IndexOutOfRangeException e)
                {
                    Client.Log("Had a problem decoding an ObjectUpdateCompressed packet: " +
                               e.ToString(), Helpers.LogLevel.Warning);
                    Client.Log(block.ToString(), Helpers.LogLevel.Warning);
                }
            }
        }
        private void PrimSeen(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
        {
            lock (Prims)
            {
                if (Prims.ContainsKey(prim.LocalID))
                {
                    Prims.Remove(prim.LocalID);
                }

                Prims.Add(prim.LocalID, prim);
                Log("Saw prim " + prim.ID.ToString());
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="simulator"></param>
        /// <param name="prim"></param>
        /// <param name="regionHandle"></param>
        /// <param name="timeDilation"></param>
        void OnNewPrim(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
        {
            PrimVisual primVisual = PrimVisual.BuildPrimVisual(prim);

            if (primVisual != null &&
                (primVisual.GetType() == typeof(PrimVisualBox) ||
                primVisual.GetType() == typeof(PrimVisualCylinder)))
            {
                lock (Prims)
                {
                    if (Prims.ContainsKey(prim.LocalID))
                    {
                        Prims.Remove(prim.LocalID);
                    }

                    Prims.Add(prim.LocalID, primVisual);
                }
            }
        }
        private void CompressedUpdateHandler(Packet packet, Simulator simulator)
        {
            ObjectUpdateCompressedPacket update = (ObjectUpdateCompressedPacket)packet;
            PrimObject prim;

            foreach (ObjectUpdateCompressedPacket.ObjectDataBlock block in update.ObjectData)
            {
                int i = 0;
                prim = new PrimObject(Client);

                try
                {
                    prim.ID = new LLUUID(block.Data, 0);
                    i += 16;
                    prim.LocalID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                        (block.Data[i++] << 16) + (block.Data[i++] << 24));

                    byte pcode = block.Data[i++];

                    if (pcode == (byte)PCode.Prim)
                    {
                        #region PrimRegion
                        prim.State = (uint)block.Data[i++];
                        i += 4; // CRC
                        prim.Material = (uint)block.Data[i++];
                        i++; // TODO: ClickAction

                        prim.Scale = new LLVector3(block.Data, i);
                        i += 12;
                        prim.Position = new LLVector3(block.Data, i);
                        i += 12;
                        prim.Rotation = new LLQuaternion(block.Data, i, true);
                        i += 12;

                        uint flags = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                            (block.Data[i++] << 16) + (block.Data[i++] << 24));

                        if ((flags & 0x02) != 0)
                        {
                            byte TreeData = block.Data[i++];

                            // TODO: Unknown byte
                            i++;

                            if (OnNewPrim != null)
                            {
                                OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                            }
                            continue;
                        }

                        if ((flags & 0x20) != 0)
                        {
                            prim.ParentID = (uint)(block.Data[i++] + (block.Data[i++] << 8) +
                            (block.Data[i++] << 16) + (block.Data[i++] << 24));
                        }
                        else
                        {
                            prim.ParentID = 0;
                        }

                        if ((flags & 0x80) != 0)
                        {
                            // TODO: Use this. What is it?
                            LLVector3 Omega = new LLVector3(block.Data, i);
                            i += 12;
                        }

                        if ((flags & 0x04) != 0)
                        {
                            string text = "";
                            while (block.Data[i] != 0)
                            {
                                text += (char)block.Data[i];
                                i++;
                            }
                            prim.Text = text;
                            i++;

                            // Text color
                            i += 4;
                        }
                        else
                        {
                            prim.Text = "";
                        }

                        if ((flags & 0x08) != 0)
                        {
                            prim.ParticleSys = new ParticleSystem(block.Data, i);
                            i += 86;
                        }

                        i += prim.SetExtraParamsFromBytes(block.Data, i);

                        //Sound data
                        if ((flags & 0x10) != 0)
                        {
                            //TODO: use this data
                            LLUUID SoundUUID = new LLUUID(block.Data, i);
                            i += 16;
                            LLUUID OwnerUUID = new LLUUID(block.Data, i);
                            i += 16;

                            if (!BitConverter.IsLittleEndian)
                            {
                                Array.Reverse(block.Data, i, 4);
                                Array.Reverse(block.Data, i + 5, 4);
                            }

                            float SoundGain = BitConverter.ToSingle(block.Data, i);
                            i += 4;
                            byte SoundFlags = block.Data[i++];
                            float SoundRadius = BitConverter.ToSingle(block.Data, i);
                            i += 4;
                        }

                        //Indicates that this is an attachment?
                        if ((flags & 0x100) != 0)
                        {
                            //A string
                            //Example: "AttachItemID STRING RW SV fa9a5ab8-1bad-b449-9873-cf5b803e664e"
                            while (block.Data[i] != 0)
                            {
                                i++;
                            }
                            i++;
                        }

                        prim.PathCurve = (uint)block.Data[i++];
                        prim.PathBegin = PrimObject.PathBeginFloat(block.Data[i++]);
                        prim.PathEnd = PrimObject.PathEndFloat(block.Data[i++]);
                        prim.PathTaperX = PrimObject.PathScaleFloat(block.Data[i++]);
                        prim.PathTaperY = PrimObject.PathScaleFloat(block.Data[i++]);
                        prim.PathShearX = PrimObject.PathShearFloat(block.Data[i++]);
                        prim.PathShearY = PrimObject.PathShearFloat(block.Data[i++]);
                        prim.PathTwist = (int)block.Data[i++];
                        prim.PathTwistBegin = (int)block.Data[i++];
                        prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat((sbyte)block.Data[i++]);
                        //prim.PathTaperX = PrimObject.PathTaperFloat(block.Data[i++]);
                        //prim.PathTaperY = PrimObject.PathTaperFloat(block.Data[i++]);
                        i += 2;
                        prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.Data[i++]);
                        prim.PathSkew = PrimObject.PathSkewFloat(block.Data[i++]);

                        prim.ProfileCurve = (uint)block.Data[i++];
                        prim.ProfileBegin = PrimObject.ProfileBeginFloat(block.Data[i++]);
                        prim.ProfileEnd = PrimObject.ProfileEndFloat(block.Data[i++]);
                        prim.ProfileHollow = (uint)block.Data[i++];

                        int textureEntryLength = (int)(block.Data[i++] + (block.Data[i++] << 8) +
                            (block.Data[i++] << 16) + (block.Data[i++] << 24));

                        prim.Textures = new TextureEntry(block.Data, i, textureEntryLength);

                        i += textureEntryLength;

                        if (i < block.Data.Length)
                        {
                            int textureAnimLength = (int)(block.Data[i++] + (block.Data[i++] << 8) +
                                (block.Data[i++] << 16) + (block.Data[i++] << 24));

                            prim.TextureAnim = new TextureAnimation(block.Data, i);
                        }

                        if (OnNewPrim != null)
                        {
                            OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                        }

                        #endregion PrimRegion
                    }
                    else if (pcode == (byte)PCode.Avatar)
                    {
                        Client.Log("######### Got an ObjectUpdateCompressed for an avatar, implement this! #########",
                            Helpers.LogLevel.Warning);
                    }
                    else if (pcode == (byte)PCode.Grass || pcode == (byte)PCode.Tree)
                    {
                        // TODO: Add new_tree and any other tree-like prims
                        ;
                    }
                    else
                    {
                        // TODO: ...
                        continue;
                    }
                }
                catch (System.IndexOutOfRangeException e)
                {
                    Client.Log("Had a problem decoding an ObjectUpdateCompressed packet: " +
                        e.ToString(), Helpers.LogLevel.Warning);
                    Client.Log(block.ToString(), Helpers.LogLevel.Warning);
                }
            }
        }
 public PrimVisualSphere(PrimObject prim)
     : base(prim)
 {
     ;
 }
 public RotationalPrimVisual(PrimObject prim)
     : base(prim)
 {
 }
        public override string Execute(string[] args, LLUUID fromAgentID)
        {
            if (args.Length != 1)
                return "Usage: import inputfile.xml";

            string name = args[0];
            Dictionary<uint, PrimObject> prims;

            currentClient = Client;

            try
            {
                XmlReader reader = XmlReader.Create(name);
                List<PrimObject> listprims = Helpers.PrimListFromXml(reader);
                reader.Close();

                // Create a dictionary indexed by the old local ID of the prims
                prims = new Dictionary<uint, PrimObject>();
                foreach (PrimObject prim in listprims)
                {
                    prims.Add(prim.LocalID, prim);
                }
            }
            catch (Exception)
            {
                return "Failed to import the object XML file, maybe it doesn't exist or is in the wrong format?";
            }

            if (!registeredCreateEvent)
            {
                TestClient.OnPrimCreated += new TestClient.PrimCreatedCallback(TestClient_OnPrimCreated);
                registeredCreateEvent = true;
            }

            // Build an organized structure from the imported prims
            Dictionary<uint, Linkset> linksets = new Dictionary<uint, Linkset>();
            foreach (PrimObject prim in prims.Values)
            {
                if (prim.ParentID == 0)
                {
                    if (linksets.ContainsKey(prim.LocalID))
                        linksets[prim.LocalID].RootPrim = prim;
                    else
                        linksets[prim.LocalID] = new Linkset(prim);
                }
                else
                {
                    if (!linksets.ContainsKey(prim.ParentID))
                        linksets[prim.ParentID] = new Linkset();

                    linksets[prim.ParentID].Children.Add(prim);
                }
            }

            primsCreated = new List<PrimObject>();
            linking = false;
            Console.WriteLine("Importing " + linksets.Count + " structures.");

            foreach (Linkset linkset in linksets.Values)
            {
                if (linkset.RootPrim.LocalID != 0)
                {
                    // HACK: Offset the root prim position so it's not lying on top of the original
                    // We need a more elaborate solution for importing with relative or absolute offsets
                    linkset.RootPrim.Position.Z += 3.0f;
                    currentPosition = linkset.RootPrim.Position;

                    // Rez the root prim with no rotation
                    LLQuaternion rootRotation = linkset.RootPrim.Rotation;
                    linkset.RootPrim.Rotation = LLQuaternion.Identity;

                    rezzingRootPrim = true;
                    currentPrim = linkset.RootPrim;

                    Client.Objects.AddPrim(Client.Network.CurrentSim, linkset.RootPrim, linkset.RootPrim.Position);

                    if (!primDone.WaitOne(10000, false))
                        return "Rez failed, timed out while creating a prim.";
                    primDone.Reset();

                    rezzingRootPrim = false;

                    // Rez the child prims
                    foreach (PrimObject prim in linkset.Children)
                    {
                        currentPrim = prim;
                        currentPosition = prim.Position + linkset.RootPrim.Position;

                        Client.Objects.AddPrim(Client.Network.CurrentSim, prim, currentPosition);

                        if (!primDone.WaitOne(10000, false))
                            return "Rez failed, timed out while creating a prim.";
                        primDone.Reset();
                    }

                    // Create a list of the local IDs of the newly created prims
                    List<uint> primIDs = new List<uint>();
                    foreach (PrimObject prim in primsCreated)
                    {
                        if (prim.LocalID != rootLocalID)
                            primIDs.Add(prim.LocalID);
                    }
                    // Make sure the root object is the last in our list so it becomes the new root
                    primIDs.Add(rootLocalID);

                    // Link and set the permissions + rotation
                    linking = true;

                    Client.Objects.LinkPrims(Client.Network.CurrentSim, primIDs);

                    Client.Objects.SetPermissions(Client.Network.CurrentSim, primIDs,
                        Helpers.PermissionWho.Everyone | Helpers.PermissionWho.Group | Helpers.PermissionWho.NextOwner,
                        Helpers.PermissionType.Copy | Helpers.PermissionType.Modify | Helpers.PermissionType.Move |
                        Helpers.PermissionType.Transfer, true);

                    Client.Objects.SetRotation(Client.Network.CurrentSim, rootLocalID, rootRotation);

                    for (int i = 0; i < linkset.Children.Count + 1; i++)
                    {
                        primDone.WaitOne(10000, false);
                        primDone.Reset();
                    }

                    linking = false;
                }
                else
                {
                    // Skip linksets with a missing root prim
                    Console.WriteLine("WARNING: Skipping a linkset with a missing root prim");
                }

                // Reset everything for the next linkset
                primsCreated.Clear();
            }

            return "Import complete.";
        }
 public Linkset(PrimObject rootPrim)
 {
     RootPrim = rootPrim;
     Children = new List<PrimObject>();
 }
 public Linkset()
 {
     RootPrim = new PrimObject();
     Children = new List<PrimObject>();
 }
        private void UpdateHandler(Packet packet, Simulator simulator)
        {
            if (OnNewPrim != null || OnNewAvatar != null)
            {
                ObjectUpdatePacket update = (ObjectUpdatePacket)packet;

                foreach (ObjectUpdatePacket.ObjectDataBlock block in update.ObjectData)
                {
                    if (block.PCode == (byte)PCode.Prim)
                    {
                        if (OnNewPrim != null)
                        {
                            // New prim spotted
                            PrimObject prim = new PrimObject(Client);

                            prim.Position = new LLVector3(block.ObjectData, 0);
                            prim.Rotation = new LLQuaternion(block.ObjectData, 36, true);

                            // TODO: Parse the rest of the ObjectData byte array fields

                            prim.LocalID = block.ID;
                            prim.State = block.State;
                            prim.ID = block.FullID;
                            prim.ParentID = block.ParentID;
                            //block.OwnerID Sound-related
                            prim.Material = block.Material;
                            prim.PathCurve = block.PathCurve;
                            prim.ProfileCurve = block.ProfileCurve;
                            prim.PathBegin = PrimObject.PathBeginFloat(block.PathBegin);
                            prim.PathEnd = PrimObject.PathEndFloat(block.PathEnd);
                            prim.PathTaperX = PrimObject.PathScaleFloat(block.PathScaleX);
                            prim.PathTaperY = PrimObject.PathScaleFloat(block.PathScaleY);
                            prim.PathShearX = PrimObject.PathShearFloat(block.PathShearX);
                            prim.PathShearY = PrimObject.PathShearFloat(block.PathShearY);
                            prim.PathTwist = block.PathTwist; //PrimObject.PathTwistFloat(block.PathTwist);
                            prim.PathTwistBegin = block.PathTwistBegin; //PrimObject.PathTwistFloat(block.PathTwistBegin);
                            prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat(block.PathRadiusOffset);
                            //prim.PathTaperX = PrimObject.PathTaperFloat((byte)block.PathTaperX);
                            //prim.PathTaperY = PrimObject.PathTaperFloat((byte)block.PathTaperY);
                            prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.PathRevolutions);
                            prim.PathSkew = PrimObject.PathSkewFloat((byte)block.PathSkew);
                            prim.ProfileBegin = PrimObject.ProfileBeginFloat(block.ProfileBegin);
                            prim.ProfileEnd = PrimObject.ProfileEndFloat(block.ProfileEnd);
                            prim.ProfileHollow = block.ProfileHollow;
                            prim.Name = Helpers.FieldToString(block.NameValue);
                            //block.Data ?
                            prim.Text = ASCIIEncoding.ASCII.GetString(block.Text);
                            //block.TextColor LLColor4U of the hovering text
                            //block.MediaURL Quicktime stream
                            prim.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length);
                            prim.TextureAnim = new TextureAnimation(block.TextureAnim, 0);
                            //block.JointType ?
                            //block.JointPivot ?
                            //block.JointAxisOrAnchor ?
                            prim.ParticleSys = new ParticleSystem(block.PSBlock, 0);
                            prim.SetExtraParamsFromBytes(block.ExtraParams, 0);
                            prim.Scale = block.Scale;
                            //block.Flags ?
                            //block.UpdateFlags ?
                            //block.ClickAction ?
                            //block.Gain Sound-related
                            //block.Sound Sound-related
                            //block.Radius Sound-related

                            if (OnNewPrim != null)
                            {
                                OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                            }
                        }
                    }
                    else if (block.PCode == (byte)PCode.Avatar)
                    {
                        if (OnNewAvatar != null)
                        {
                            Avatar avatar = new Avatar();

                            string FirstName = "";
                            string LastName = "";
                            string GroupName = "";

                            //avatar.CollisionPlane = new LLQuaternion(block.ObjectData, 0);
                            avatar.Position = new LLVector3(block.ObjectData, 16);
                            avatar.Rotation = new LLQuaternion(block.ObjectData, 52, true);

                            // TODO: Parse the rest of the ObjectData byte array fields

                            ParseAvName(Helpers.FieldToString(block.NameValue), ref FirstName, ref LastName, ref GroupName);

                            avatar.ID = block.FullID;
                            avatar.LocalID = block.ID;
                            avatar.Name = FirstName + " " + LastName;
                            avatar.GroupName = GroupName;
                            avatar.Online = true;
                            avatar.CurrentRegion = simulator.Region;

                            avatar.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length);

                            if (FirstName == Client.Self.FirstName && LastName == Client.Self.LastName)
                            {
                                // Update our avatar
                                Client.Self.LocalID = avatar.LocalID;
                                Client.Self.Position = avatar.Position;
                                Client.Self.Rotation = avatar.Rotation;
                            }
                            else
                            {
                                if (OnNewAvatar != null)
                                {
                                    OnNewAvatar(simulator, avatar, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                        }
                    }
                    else if (block.PCode == (byte)PCode.Grass)
                    {
                        // FIXME: Handle grass objects
                        ;
                    }
                    else if (block.PCode == (byte)PCode.Tree)
                    {
                        // FIXME: Handle tree objects
                        ;
                    }
                    else if (block.PCode == (byte)PCode.ParticleSystem)
                    {
                        ;
                    }
                    else
                    {
                        // FIXME: How many of the PCodes do we actually need to handle?
                        ;
                    }
                }
            }
        }
        private void Objects_OnNewPrim(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
        {
            if (imgManager == null)
            {
                Console.WriteLine("ImageManager not ready yet, queueing Prim textures.");
                TextureQueue.Enqueue(prim.Textures.DefaultTexture.TextureID);

                foreach (TextureEntryFace tef in prim.Textures.FaceTextures.Values)
                {
                    TextureQueue.Enqueue(tef.TextureID);
                }
            }
            else
            {
                if ((prim.Textures.DefaultTexture != null) && (prim.Textures.DefaultTexture.TextureID != null))
                {
                    if (imgManager.isCachedImage(prim.Textures.DefaultTexture.TextureID) == false)
                    {
                        imgManager.RequestImageAsync(prim.Textures.DefaultTexture.TextureID);
                    }
                    else
                    {
                        Console.WriteLine("Already cached: " + prim.Textures.DefaultTexture.TextureID);
                    }
                }

                if (prim.Textures.FaceTextures != null)
                {
                    foreach (TextureEntryFace tef in prim.Textures.FaceTextures.Values)
                    {
                        if (imgManager.isCachedImage(tef.TextureID) == false)
                        {
                            imgManager.RequestImageAsync(tef.TextureID);
                        }
                        else
                        {
                            Console.WriteLine("Already cached: " + tef.TextureID);
                        }
                    }
                }
            }
        }
        private void cmdImport_Click(object sender, System.EventArgs e)
        {
            OpenFileDialog openDialog = new OpenFileDialog();
            openDialog.Title = "Open Prim.Blender File";
            openDialog.Filter = "All files (*.*)|*.*|Prim files (*.prims)|*.prims" ;
            openDialog.FilterIndex = 2;

            if(openDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            XmlDocument xml = new XmlDocument();
            XmlNodeList list = null;

            try
            {
                // Try to load the xml file
                xml.Load(openDialog.FileName);

                //If there is a document and it has children,
                if(xml != null && xml.HasChildNodes)
                {
                    //Get the children into the temp list
                    list = xml.GetElementsByTagName("primitive");
                }
                else
                {
                    txtLog.AppendText("ERROR: Failed to parse " + openDialog.FileName + "\n");
                    return;
                }
            }
            catch (Exception err)
            {
                txtLog.AppendText("ERROR: " + err.ToString() + "\n");
                return;
            }

            foreach (XmlNode node in list)
            {
                txtLog.AppendText("Parsing primitive " + node.Attributes["key"].Value + "\n");

                XmlNode properties = node["properties"];

                PrimObject prim = new PrimObject(new LLUUID("8955674724cb43ed920b47caed15465f"));

                prim.Material = Convert.ToUInt16(properties["material"].Attributes["val"].Value);
                prim.Name = node.Attributes["key"].Value;
                // Either PathBegin/End or ProfileBegin/End should be dimple
                prim.PathBegin = PrimObject.PathBeginByte(Convert.ToSingle(properties["cut"].Attributes["x"].Value));
                prim.PathEnd = PrimObject.PathEndByte(Convert.ToSingle(properties["cut"].Attributes["y"].Value));
                prim.PathRadiusOffset = PrimObject.PathRadiusOffsetByte(Convert.ToSingle(properties["radiusoffset"].Attributes["val"].Value));
                prim.PathRevolutions = PrimObject.PathRevolutionsByte(Convert.ToSingle(properties["revolutions"].Attributes["val"].Value));
                prim.PathScaleX = PrimObject.PathScaleByte(Convert.ToSingle(properties["topsize"].Attributes["x"].Value));
                prim.PathScaleY = PrimObject.PathScaleByte(Convert.ToSingle(properties["topsize"].Attributes["y"].Value));
                prim.PathShearX = PrimObject.PathShearByte(Convert.ToSingle(properties["topshear"].Attributes["x"].Value));
                prim.PathShearY = PrimObject.PathShearByte(Convert.ToSingle(properties["topshear"].Attributes["y"].Value));
                prim.PathSkew = PrimObject.PathSkewByte(Convert.ToSingle(properties["skew"].Attributes["val"].Value));
                prim.PathTaperX = PrimObject.PathTaperByte(Convert.ToSingle(properties["taper"].Attributes["x"].Value));
                prim.PathTaperY = PrimObject.PathTaperByte(Convert.ToSingle(properties["taper"].Attributes["y"].Value));
                prim.PathTwist = PrimObject.PathTwistByte(Convert.ToSingle(properties["twist"].Attributes["y"].Value));
                prim.PathTwistBegin = PrimObject.PathTwistByte(Convert.ToSingle(properties["twist"].Attributes["x"].Value));
                prim.ProfileBegin = PrimObject.ProfileBeginByte(Convert.ToSingle(properties["cut"].Attributes["x"].Value));
                prim.ProfileEnd = PrimObject.ProfileEndByte(Convert.ToSingle(properties["cut"].Attributes["y"].Value));
                ushort curve = Convert.ToUInt16(properties["type"].Attributes["val"].Value);
                switch (curve)
                {
                    case 0:
                        // Box
                        prim.ProfileCurve = 1;
                        prim.PathCurve = 16;
                        break;
                    case 1:
                        // Cylinder
                        prim.ProfileCurve = 0;
                        prim.PathCurve = 16;
                        break;
                    case 2:
                        // Prism
                        prim.ProfileCurve = 3;
                        prim.PathCurve = 16;
                        break;
                    case 3:
                        // Sphere
                        prim.ProfileCurve = 5;
                        prim.PathCurve = 32;
                        break;
                    case 4:
                        // Torus
                        prim.ProfileCurve = 0;
                        prim.PathCurve = 32;
                        break;
                    case 5:
                        // Tube
                        prim.ProfileCurve = 1;
                        prim.PathCurve = 32;
                        break;
                    case 6:
                        // Ring
                        prim.ProfileCurve = 3;
                        prim.PathCurve = 16;
                        break;
                }
                prim.ProfileHollow = Convert.ToUInt32(properties["hollow"].Attributes["val"].Value);
                prim.Rotation = new LLQuaternion(
                    Convert.ToSingle(properties["rotation"].Attributes["x"].Value),
                    Convert.ToSingle(properties["rotation"].Attributes["y"].Value),
                    Convert.ToSingle(properties["rotation"].Attributes["z"].Value),
                    Convert.ToSingle(properties["rotation"].Attributes["s"].Value));
                prim.Scale = new LLVector3(
                    Convert.ToSingle(properties["size"].Attributes["x"].Value),
                    Convert.ToSingle(properties["size"].Attributes["y"].Value),
                    Convert.ToSingle(properties["size"].Attributes["z"].Value));

                LLVector3 position = new LLVector3(
                    Convert.ToSingle(properties["position"].Attributes["x"].Value) + (float)Client.Avatar.Position.X,
                    Convert.ToSingle(properties["position"].Attributes["y"].Value) + (float)Client.Avatar.Position.Y,
                    Convert.ToSingle(properties["position"].Attributes["z"].Value) + (float)Client.Avatar.Position.Z + 50.0F);
                prim.Position = position;

                CurrentPrim = prim;
                WaitingOnUpdate = true;

                Client.CurrentRegion.RezObject(prim, position, new LLVector3(Client.Avatar.Position));

                while (WaitingOnUpdate)
                {
                    System.Threading.Thread.Sleep(100);
                    Application.DoEvents();
                }

                txtLog.AppendText("Rezzed primitive with UUID " + CurrentPrim.UUID + " and ID " + CurrentPrim.ID + " \n");

                Hashtable blocks = new Hashtable();
                Hashtable fields = new Hashtable();

                /*fields["ObjectLocalID"] = CurrentPrim.ID;
                blocks[fields] = "ObjectData";

                fields = new Hashtable();

                fields["AgentID"] = Client.Network.AgentID;
                blocks[fields] = "AgentData";

                Packet packet = PacketBuilder.BuildPacket("ObjectSelect", Client.Protocol, blocks, Helpers.MSG_RELIABLE);
                Client.Network.SendPacket(packet);

                System.Threading.Thread.Sleep(100);*/
                Packet packet;

                byte[] byteArray = new byte[12];
                Array.Copy(position.GetBytes(), byteArray, 12);

                fields["Data"] = byteArray;
                fields["Type"] = (byte)9;
                fields["ObjectLocalID"] = CurrentPrim.ID;
                blocks[fields] = "ObjectData";

                fields = new Hashtable();

                fields["AgentID"] = Client.Network.AgentID;
                blocks[fields] = "AgentData";

                packet = PacketBuilder.BuildPacket("MultipleObjectUpdate", Client.Protocol, blocks, Helpers.MSG_RELIABLE);
                Client.Network.SendPacket(packet);
                Client.Network.SendPacket(packet);
                Client.Network.SendPacket(packet);

                System.Threading.Thread.Sleep(500);
            }
        }
 void AttachmentSeen(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
 {
     lock (Attachments)
     {
         Attachments.Add(prim.LocalID);
     }
 }
        private void UpdateHandler(Packet packet, Simulator simulator)
        {
            if (OnNewPrim != null || OnNewAvatar != null)
            {
                ObjectUpdatePacket update = (ObjectUpdatePacket)packet;

                foreach (ObjectUpdatePacket.ObjectDataBlock block in update.ObjectData)
                {
                    if (block.PCode == (byte)PCode.Prim)
                    {
                        if (OnNewPrim != null)
                        {
                            // New prim spotted
                            PrimObject prim = new PrimObject(Client);

                            prim.Position = new LLVector3(block.ObjectData, 0);
                            prim.Rotation = new LLQuaternion(block.ObjectData, 36, true);

                            // TODO: Parse the rest of the ObjectData byte array fields

                            prim.LocalID  = block.ID;
                            prim.State    = block.State;
                            prim.ID       = block.FullID;
                            prim.ParentID = block.ParentID;
                            //block.OwnerID Sound-related
                            prim.Material         = block.Material;
                            prim.PathCurve        = block.PathCurve;
                            prim.ProfileCurve     = block.ProfileCurve;
                            prim.PathBegin        = PrimObject.PathBeginFloat(block.PathBegin);
                            prim.PathEnd          = PrimObject.PathEndFloat(block.PathEnd);
                            prim.PathTaperX       = PrimObject.PathScaleFloat(block.PathScaleX);
                            prim.PathTaperY       = PrimObject.PathScaleFloat(block.PathScaleY);
                            prim.PathShearX       = PrimObject.PathShearFloat(block.PathShearX);
                            prim.PathShearY       = PrimObject.PathShearFloat(block.PathShearY);
                            prim.PathTwist        = block.PathTwist;      //PrimObject.PathTwistFloat(block.PathTwist);
                            prim.PathTwistBegin   = block.PathTwistBegin; //PrimObject.PathTwistFloat(block.PathTwistBegin);
                            prim.PathRadiusOffset = PrimObject.PathRadiusOffsetFloat(block.PathRadiusOffset);
                            //prim.PathTaperX = PrimObject.PathTaperFloat((byte)block.PathTaperX);
                            //prim.PathTaperY = PrimObject.PathTaperFloat((byte)block.PathTaperY);
                            prim.PathRevolutions = PrimObject.PathRevolutionsFloat(block.PathRevolutions);
                            prim.PathSkew        = PrimObject.PathSkewFloat((byte)block.PathSkew);
                            prim.ProfileBegin    = PrimObject.ProfileBeginFloat(block.ProfileBegin);
                            prim.ProfileEnd      = PrimObject.ProfileEndFloat(block.ProfileEnd);
                            prim.ProfileHollow   = block.ProfileHollow;
                            prim.Name            = Helpers.FieldToString(block.NameValue);
                            //block.Data ?
                            prim.Text = ASCIIEncoding.ASCII.GetString(block.Text);
                            //block.TextColor LLColor4U of the hovering text
                            //block.MediaURL Quicktime stream
                            prim.Textures    = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length);
                            prim.TextureAnim = new TextureAnimation(block.TextureAnim, 0);
                            //block.JointType ?
                            //block.JointPivot ?
                            //block.JointAxisOrAnchor ?
                            prim.ParticleSys = new ParticleSystem(block.PSBlock, 0);
                            prim.SetExtraParamsFromBytes(block.ExtraParams, 0);
                            prim.Scale = block.Scale;
                            //block.Flags ?
                            //block.UpdateFlags ?
                            //block.ClickAction ?
                            //block.Gain Sound-related
                            //block.Sound Sound-related
                            //block.Radius Sound-related

                            if (OnNewPrim != null)
                            {
                                OnNewPrim(simulator, prim, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                            }
                        }
                    }
                    else if (block.PCode == (byte)PCode.Avatar)
                    {
                        if (OnNewAvatar != null)
                        {
                            Avatar avatar = new Avatar();

                            string FirstName = "";
                            string LastName  = "";
                            string GroupName = "";

                            //avatar.CollisionPlane = new LLQuaternion(block.ObjectData, 0);
                            avatar.Position = new LLVector3(block.ObjectData, 16);
                            avatar.Rotation = new LLQuaternion(block.ObjectData, 52, true);

                            // TODO: Parse the rest of the ObjectData byte array fields

                            ParseAvName(Helpers.FieldToString(block.NameValue), ref FirstName, ref LastName, ref GroupName);

                            avatar.ID            = block.FullID;
                            avatar.LocalID       = block.ID;
                            avatar.Name          = FirstName + " " + LastName;
                            avatar.GroupName     = GroupName;
                            avatar.Online        = true;
                            avatar.CurrentRegion = simulator.Region;

                            avatar.Textures = new TextureEntry(block.TextureEntry, 0, block.TextureEntry.Length);

                            if (FirstName == Client.Self.FirstName && LastName == Client.Self.LastName)
                            {
                                // Update our avatar
                                Client.Self.LocalID  = avatar.LocalID;
                                Client.Self.Position = avatar.Position;
                                Client.Self.Rotation = avatar.Rotation;
                            }
                            else
                            {
                                if (OnNewAvatar != null)
                                {
                                    OnNewAvatar(simulator, avatar, update.RegionData.RegionHandle, update.RegionData.TimeDilation);
                                }
                            }
                        }
                    }
                    else if (block.PCode == (byte)PCode.Grass)
                    {
                        // FIXME: Handle grass objects
                        ;
                    }
                    else if (block.PCode == (byte)PCode.Tree)
                    {
                        // FIXME: Handle tree objects
                        ;
                    }
                    else if (block.PCode == (byte)PCode.ParticleSystem)
                    {
                        ;
                    }
                    else
                    {
                        // FIXME: How many of the PCodes do we actually need to handle?
                        ;
                    }
                }
            }
        }
 public static PrimVisual BuildPrimVisual(PrimObject prim)
 {
     if (prim.ProfileCurve == 1 && prim.PathCurve == 16)
     {
         // PRIM_TYPE_BOX
         return new PrimVisualBox(prim);
     }
     else if (prim.ProfileCurve == 0 && prim.PathCurve == 16)
     {
         // PRIM_TYPE_CYLINDER
         return new PrimVisualCylinder(prim);
     }
     else if (prim.ProfileCurve == 3 && prim.PathCurve == 16)
     {
         // PRIM_TYPE_PRISM
         return new PrimVisualPrism(prim);
     }
     else if (prim.ProfileCurve == 5 && prim.PathCurve == 32)
     {
         // PRIM_TYPE_SPHERE
         return new PrimVisualSphere(prim);
     }
     else if (prim.ProfileCurve == 0 && prim.PathCurve == 32)
     {
         // PRIM_TYPE_TORUS
         return new PrimVisualTorus(prim);
     }
     else if (prim.ProfileCurve == 1 && prim.PathCurve == 32)
     {
         // PRIM_TYPE_TUBE
         return new PrimVisualTube(prim);
     }
     else if (prim.ProfileCurve == 3 && prim.PathCurve == 32)
     {
         // PRIM_TYPE_RING
         return new PrimVisualRing(prim);
     }
     else
     {
         return null;
     }
 }
 public PrimVisualPrism(PrimObject prim)
     : base(prim)
 {
     ;
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="prim"></param>
        /// <param name="position"></param>
        /// <param name="avatarPosition"></param>
        public void RezObject(PrimObject prim, LLVector3 position, LLVector3 rayStart, 
            LLUUID groupID)
        {
            ObjectAddPacket add = new ObjectAddPacket();
            add.AgentData.AgentID = Client.Network.AgentID;
            add.AgentData.SessionID = Client.Network.SessionID;
            add.AgentData.GroupID = groupID;
            // TODO: Why 2?
            add.ObjectData.AddFlags = 2;
            add.ObjectData.BypassRaycast = 1;
            add.ObjectData.Material = (byte)prim.Material;
            add.ObjectData.PathBegin = PrimObject.PathBeginByte(prim.PathBegin);
            add.ObjectData.PathCurve = (byte)prim.PathCurve;
            add.ObjectData.PathEnd = PrimObject.PathEndByte(prim.PathEnd);
            add.ObjectData.PathRadiusOffset = PrimObject.PathRadiusOffsetByte(prim.PathRadiusOffset);
            add.ObjectData.PathRevolutions = PrimObject.PathRevolutionsByte(prim.PathRevolutions);
            add.ObjectData.PathScaleX = PrimObject.PathScaleByte(prim.PathScaleX);
            add.ObjectData.PathScaleY = PrimObject.PathScaleByte(prim.PathScaleY);
            add.ObjectData.PathShearX = PrimObject.PathShearByte(prim.PathShearX);
            add.ObjectData.PathShearY = PrimObject.PathShearByte(prim.PathShearY);
            add.ObjectData.PathSkew = PrimObject.PathSkewByte(prim.PathSkew);
            add.ObjectData.PathTaperX = PrimObject.PathTaperByte(prim.PathTaperX);
            add.ObjectData.PathTaperY = PrimObject.PathTaperByte(prim.PathTaperY);
            add.ObjectData.PathTwist = PrimObject.PathTwistByte(prim.PathTwist);
            add.ObjectData.PathTwistBegin = PrimObject.PathTwistByte(prim.PathTwistBegin);
            add.ObjectData.PCode = (byte)prim.PCode;
            add.ObjectData.ProfileBegin = PrimObject.ProfileBeginByte(prim.ProfileBegin);
            add.ObjectData.ProfileCurve = (byte)prim.ProfileCurve;
            add.ObjectData.ProfileEnd = PrimObject.ProfileEndByte(prim.ProfileEnd);
            add.ObjectData.ProfileHollow = (byte)prim.ProfileHollow;
            add.ObjectData.RayEnd = position;
            add.ObjectData.RayEndIsIntersection = 0;
            add.ObjectData.RayStart = rayStart;
            add.ObjectData.RayTargetID = LLUUID.GenerateUUID();
            add.ObjectData.Rotation = prim.Rotation;
            add.ObjectData.Scale = prim.Scale;
            add.ObjectData.State = (byte)prim.State;
            if (prim.Textures != null)
            {
                add.ObjectData.TextureEntry = prim.Textures.ToBytes();
            }
            else
            {
                add.ObjectData.TextureEntry = new byte[0];
            }

            Client.Network.SendPacket(add);
        }
        /// <summary>
        /// Create, or "rez" a new prim object in a simulator
        /// </summary>
        /// <param name="simulator">The target simulator</param>
        /// <param name="prim">The prim object to rez</param>
        /// <param name="position">An approximation of the position at which to rez the prim</param>
        /// <remarks>Due to the way client prim rezzing is done on the server,
        /// the requested position for an object is only close to where the prim
        /// actually ends up. If you desire exact placement you'll need to 
        /// follow up by moving the object after it has been created.</remarks>
        public void AddPrim(Simulator simulator, PrimObject prim, LLVector3 position)
        {
            ObjectAddPacket packet = new ObjectAddPacket();

            packet.AgentData.AgentID = Client.Network.AgentID;
            packet.AgentData.SessionID = Client.Network.SessionID;
            packet.AgentData.GroupID = prim.GroupID;

            packet.ObjectData.State = (byte)prim.State;
            packet.ObjectData.AddFlags = (uint)ObjectFlags.CreateSelected;
            packet.ObjectData.PCode = (byte)PCode.Prim;

            packet.ObjectData.Material = (byte)prim.Material;
            packet.ObjectData.Scale = prim.Scale;
            packet.ObjectData.Rotation = prim.Rotation;

            packet.ObjectData.PathBegin = PrimObject.PathBeginByte(prim.PathBegin);
            packet.ObjectData.PathCurve = (byte)prim.PathCurve;
            packet.ObjectData.PathEnd = PrimObject.PathEndByte(prim.PathEnd);
            packet.ObjectData.PathRadiusOffset = PrimObject.PathRadiusOffsetByte(prim.PathRadiusOffset);
            packet.ObjectData.PathRevolutions = PrimObject.PathRevolutionsByte(prim.PathRevolutions);
            packet.ObjectData.PathScaleX = PrimObject.PathScaleByte(prim.PathScaleX);
            packet.ObjectData.PathScaleY = PrimObject.PathScaleByte(prim.PathScaleY);
            packet.ObjectData.PathShearX = PrimObject.PathShearByte(prim.PathShearX);
            packet.ObjectData.PathShearY = PrimObject.PathShearByte(prim.PathShearY);
            packet.ObjectData.PathSkew = PrimObject.PathSkewByte(prim.PathSkew);
            packet.ObjectData.PathTaperX = PrimObject.PathTaperByte(prim.PathTaperX);
            packet.ObjectData.PathTaperY = PrimObject.PathTaperByte(prim.PathTaperY);
            packet.ObjectData.PathTwist = (sbyte)prim.PathTwist;
            packet.ObjectData.PathTwistBegin = (sbyte)prim.PathTwistBegin;

            packet.ObjectData.ProfileCurve = (byte)prim.ProfileCurve;
            packet.ObjectData.ProfileBegin = PrimObject.ProfileBeginByte(prim.ProfileBegin);
            packet.ObjectData.ProfileEnd = PrimObject.ProfileEndByte(prim.ProfileEnd);
            packet.ObjectData.ProfileHollow = (byte)prim.ProfileHollow;

            packet.ObjectData.RayStart = position;
            packet.ObjectData.RayEnd = position;
            packet.ObjectData.RayEndIsIntersection = 0;
            packet.ObjectData.RayTargetID = LLUUID.Zero;
            packet.ObjectData.BypassRaycast = 1;

            // TODO: This is no longer a field in ObjectAdd. Detect if there actually is 
            // texture information for this prim and send an ObjectUpdate
            //packet.ObjectData.TextureEntry = prim.Textures.GetBytes();

            Client.Network.SendPacket(packet, simulator);
        }
        private void cmdBuild_Click(object sender, System.EventArgs e)
        {
            cmdBuild.Enabled = false;

            PrimObject prim = new PrimObject(new LLUUID("8955674724cb43ed920b47caed15465f"));

            prim.Material = (uint)numMaterial.Value;
            prim.PathBegin = PrimObject.PathBeginByte((float)numPathBegin.Value);
            prim.PathEnd = PrimObject.PathEndByte((float)numPathEnd.Value);
            prim.PathRadiusOffset = PrimObject.PathRadiusOffsetByte((float)numPathRadiusOffset.Value);
            prim.PathRevolutions = PrimObject.PathRevolutionsByte((float)numPathRevolutions.Value);
            prim.PathScaleX = PrimObject.PathScaleByte((float)numPathScaleX.Value);
            prim.PathScaleY = PrimObject.PathScaleByte((float)numPathScaleY.Value);
            prim.PathShearX = PrimObject.PathShearByte((float)numPathShearX.Value);
            prim.PathShearY = PrimObject.PathShearByte((float)numPathShearY.Value);
            prim.PathTaperX = PrimObject.PathTaperByte((float)numPathTaperX.Value);
            prim.PathTaperY = PrimObject.PathTaperByte((float)numPathTaperY.Value);
            prim.PathTwistBegin = PrimObject.PathTwistByte((float)numPathTwistBegin.Value);
            prim.PathTwist = PrimObject.PathTwistByte((float)numPathTwist.Value);
            prim.ProfileBegin = PrimObject.ProfileBeginByte((float)numProfileBegin.Value);
            prim.ProfileEnd = PrimObject.ProfileEndByte((float)numProfileEnd.Value);
            prim.PathSkew = PrimObject.PathSkewByte((float)numPathSkew.Value);
            prim.ProfileCurve = (uint)numProfileCurve.Value;
            prim.PathCurve = (uint)numPathCurve.Value;
            prim.ProfileHollow = (uint)numProfileHollow.Value;
            prim.Rotation.X = (float)numRotationX.Value;
            prim.Rotation.Y = (float)numRotationY.Value;
            prim.Rotation.Z = (float)numRotationZ.Value;
            prim.Rotation.S = (float)numRotationS.Value;
            prim.Scale.X = (float)numScaleX.Value;
            prim.Scale.Y = (float)numScaleY.Value;
            prim.Scale.Z = (float)numScaleZ.Value;
            prim.Position.X = (float)numPositionX.Value;
            prim.Position.Y = (float)numPositionY.Value;
            prim.Position.Z = (float)numPositionZ.Value;

            Client.CurrentRegion.RezObject(prim, prim.Position, new LLVector3(Client.Avatar.Position));

            // Rate limiting
            System.Threading.Thread.Sleep(250);

            cmdBuild.Enabled = true;
        }
 public LinearPrimVisual(PrimObject prim)
     : base(prim)
 {
 }
        private void Objects_OnNewPrim(Simulator simulator, PrimObject prim, ulong regionHandle, ushort timeDilation)
        {
            lock (SimPrims)
            {
                if (!SimPrims.ContainsKey(simulator))
                {
                    SimPrims[simulator] = new Dictionary<uint, PrimObject>(10000);
                }

                SimPrims[simulator][prim.LocalID] = prim;
            }

            if ((prim.Flags & ObjectFlags.CreateSelected) != 0 && OnPrimCreated != null)
            {
                OnPrimCreated(simulator, prim);
            }
        }