예제 #1
0
        public void SetMediaEntry(ISceneChildEntity part, int face, MediaEntry me)
        {
            CheckFaceParam(part, face);

            if (null == part.Shape.Media)
            {
                if (me == null)
                {
                    return;
                }
                else
                {
                    part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
                }
            }

            if (part.Shape.Media[face] == null) //If it doesn't exist, set the default parameters for it
            {
                me.InteractPermissions = MediaPermission.All;
            }
            lock (part.Shape.Media)
                part.Shape.Media[face] = me;

            UpdateMediaUrl(part, UUID.Zero);

            SetPartMediaFlags(part, face, me != null);

            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
            part.TriggerScriptChangedEvent(Changed.MEDIA);
        }
예제 #2
0
        public void SetMediaEntry(ISceneChildEntity part, int face, MediaEntry me)
        {
            CheckFaceParam(part, face);

            if (null == part.Shape.Media)
            {
                if (me == null)
                {
                    return;
                }
                else
                {
                    part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
                }
            }

            lock (part.Shape.Media)
                part.Shape.Media[face] = me;

            UpdateMediaUrl(part, UUID.Zero);

            SetPartMediaFlags(part, face, me != null);

            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
            part.TriggerScriptChangedEvent(Changed.MEDIA);
        }
예제 #3
0
        private void growTrees()
        {
            foreach (Copse copse in m_copse)
            {
                if (!copse.m_frozen)
                {
                    foreach (UUID tree in copse.m_trees)
                    {
                        IEntity ent;
                        if (m_scene.Entities.TryGetValue(tree, out ent))
                        {
                            ISceneChildEntity s_tree = ((ISceneEntity)ent).RootChild;

                            if (s_tree.Scale.X < copse.m_maximum_scale.X && s_tree.Scale.Y < copse.m_maximum_scale.Y && s_tree.Scale.Z < copse.m_maximum_scale.Z)
                            {
                                s_tree.Scale += copse.m_rate;
                                s_tree.ParentEntity.HasGroupChanged = true;
                                s_tree.ScheduleUpdate(PrimUpdateFlags.FindBest);
                            }
                        }
                        else
                        {
                            MainConsole.Instance.DebugFormat("[TREES]: Tree not in scene {0}", tree);
                        }
                    }
                }
            }
        }
        public void PlayfwdState(ISceneChildEntity part)
        {
            if (part != null)
            {
                bool ChangedScale = false;
                bool ChangedRot   = false;
                bool ChangedPos   = false;
                part.Undoing = true;

                if (part.UUID == part.ParentEntity.UUID)
                {
                    if (Position != Vector3.Zero)
                    {
                        ChangedPos = true;
                        part.ParentEntity.AbsolutePosition = Position;
                    }
                    if (Rotation != Quaternion.Identity)
                    {
                        ChangedRot = true;
                        part.UpdateRotation(Rotation);
                    }
                    if (Scale != Vector3.Zero)
                    {
                        ChangedScale = true;
                        part.Resize(Scale);
                    }

                    foreach (
                        ISceneChildEntity child in
                        part.ParentEntity.ChildrenEntities().Where(child => child.UUID != part.UUID))
                    {
                        child.Redo(); //No updates here, child redo will do it on their own
                    }
                }
                else
                {
                    if (Position != Vector3.Zero)
                    {
                        ChangedPos = true;
                        part.FixOffsetPosition(Position, false);
                    }
                    if (Rotation != Quaternion.Identity)
                    {
                        ChangedRot = true;
                        part.ParentEntity.Rotation = (Rotation);
                    }
                    if (Scale != Vector3.Zero)
                    {
                        ChangedScale = true;
                        part.Resize(Scale);
                    }
                }

                part.ScheduleUpdate((ChangedScale ? PrimUpdateFlags.Shape : PrimUpdateFlags.None) |
                                    (ChangedPos ? PrimUpdateFlags.Position : PrimUpdateFlags.None) |
                                    (ChangedRot ? PrimUpdateFlags.Rotation : PrimUpdateFlags.None));
                part.Undoing = false;
            }
        }
예제 #5
0
        public void PlaybackState(ISceneChildEntity part)
        {
            if (part != null)
            {
                part.Undoing = true;

                bool ChangedScale = false;
                bool ChangedPos   = false;

                if (part.UUID == part.ParentEntity.UUID)
                {
                    if (Position != Vector3.Zero)
                    {
                        ChangedPos = true;
                        part.ParentEntity.AbsolutePosition = Position;
                    }
                    part.SetRotationOffset(true, Rotation, true);
                    if (Scale != Vector3.Zero)
                    {
                        ChangedScale = true;
                        part.Scale   = Scale;
                    }

                    foreach (
                        ISceneChildEntity child in
                        part.ParentEntity.ChildrenEntities().Where(child => child.UUID != part.UUID))
                    {
                        child.Undo();  //No updates here, child undo will do it on their own
                    }
                }
                else
                {
                    if (Position != Vector3.Zero)
                    {
                        ChangedPos = true;
                        part.FixOffsetPosition(Position, false);
                    }
                    part.UpdateRotation(Rotation);
                    if (Scale != Vector3.Zero)
                    {
                        ChangedScale = true;
                        part.Resize(Scale);
                    }
                }
                part.Undoing = false;
                var updateFlags =
                    (ChangedScale ? PrimUpdateFlags.Shape : PrimUpdateFlags.None) |
                    (ChangedPos ? PrimUpdateFlags.Position : PrimUpdateFlags.None) |
                    PrimUpdateFlags.Rotation;

                part.ScheduleUpdate(updateFlags);
            }
        }
        // Xantor 20080528: Clear prim data of sound instead
        public void llStopSound()
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return;
            }

            m_host.AdjustSoundGain(0);
            lock (m_host.ParentEntity.LoopSoundSlavePrims) {
                if (m_host.ParentEntity.LoopSoundMasterPrim == m_host.UUID)
                {
                    foreach (UUID child in m_host.ParentEntity.LoopSoundSlavePrims)
                    {
                        ISceneChildEntity part = m_host.ParentEntity.GetChildPart(child);
                        if (part == null)
                        {
                            continue;
                        }
                        part.Sound      = UUID.Zero;
                        part.SoundGain  = 0;
                        part.SoundFlags = (byte)SoundFlags.None;
                        part.AdjustSoundGain(0);
                        part.ScheduleUpdate(PrimUpdateFlags.FindBest);
                    }
                    m_host.ParentEntity.LoopSoundMasterPrim = UUID.Zero;
                    m_host.ParentEntity.LoopSoundSlavePrims.Clear();
                }
                else
                {
                    if (m_host.ParentEntity.LoopSoundSlavePrims.Contains(m_host.UUID))
                    {
                        m_host.Sound      = UUID.Zero;
                        m_host.SoundGain  = 0;
                        m_host.SoundFlags = (byte)SoundFlags.None;
                        m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
                    }
                    else
                    {
                        m_host.Sound      = UUID.Zero;
                        m_host.SoundGain  = 0;
                        m_host.SoundFlags = (byte)SoundFlags.Stop | (byte)SoundFlags.None;
                        m_host.ScheduleUpdate(PrimUpdateFlags.FindBest);
                    }
                }
            }
        }
        public void llLoopSoundMaster(string sound, double volume)
        {
            if (!ScriptProtection.CheckThreatLevel(ThreatLevel.None, "LSL", m_host, "LSL", m_itemID))
            {
                return;
            }

            lock (m_host.ParentEntity.LoopSoundSlavePrims) {
                m_host.ParentEntity.LoopSoundMasterPrim = m_host.UUID;
                foreach (UUID child in m_host.ParentEntity.LoopSoundSlavePrims)
                {
                    ISceneChildEntity part = m_host.ParentEntity.GetChildPart(child);
                    if (part == null)
                    {
                        continue;
                    }
                    part.Sound     = KeyOrName(sound, AssetType.Sound, true);
                    part.SoundGain = volume;
                    part.AdjustSoundGain(volume);
                    part.SoundFlags = (byte)SoundFlags.Loop; // looping
                    if (FloatAlmostEqual(part.SoundRadius, 0))
                    {
                        part.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
                    }
                    part.ScheduleUpdate(PrimUpdateFlags.FindBest);
                }
            }
            //if (m_host.Sound != UUID.Zero)
            //    llStopSound();

            m_host.AdjustSoundGain(volume);
            m_host.Sound      = KeyOrName(sound, AssetType.Sound, true);
            m_host.SoundGain  = volume;
            m_host.SoundFlags = (byte)SoundFlags.Loop; // looping
            if (FloatAlmostEqual(m_host.SoundRadius, 0))
            {
                m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
            }
            m_host.ScheduleUpdate(PrimUpdateFlags.ForcedFullUpdate);
        }
예제 #8
0
        /// <summary>
        ///     Handle an update of media textures.
        /// </summary>
        /// <param name="path">Path on which this request was made</param>
        /// <param name="omu"></param>
        /// <returns></returns>
        protected byte[] HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
        {
            UUID primId = omu.PrimID;

            ISceneChildEntity part = m_scene.GetSceneObjectPart(primId);

            if (null == part)
            {
                MainConsole.Instance.WarnFormat(
                    "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
                    primId, m_scene.RegionInfo.RegionName);
                return(MainServer.BlankResponse);
            }

//            MainConsole.Instance.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);

//            for (int i = 0; i < omu.FaceMedia.Length; i++)
//            {
//                MediaEntry me = omu.FaceMedia[i];
//                string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD()));
//                MainConsole.Instance.DebugFormat("[MOAP]: Face {0} [{1}]", i, v);
//            }

            if (omu.FaceMedia.Length > part.GetNumberOfSides())
            {
                MainConsole.Instance.WarnFormat(
                    "[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces.  Dropping request.",
                    omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
                return(MainServer.BlankResponse);
            }

            UUID agentId = default(UUID);

            lock (m_omCapUsers)
                agentId = m_omCapUsers[path];

            List <MediaEntry> media = part.Shape.Media;

            if (null == media)
            {
//                MainConsole.Instance.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name);
                part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia);

                for (int i = 0; i < omu.FaceMedia.Length; i++)
                {
                    if (omu.FaceMedia[i] != null)
                    {
                        // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
                        // overwritten.  Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
                        // directly.
                        SetPartMediaFlags(part, i, true);
//                        MainConsole.Instance.DebugFormat(
//                            "[MOAP]: Media flags for face {0} is {1}",
//                            i, part.Shape.Textures.FaceTextures[i].MediaFlags);
                    }
                }
            }
            else
            {
                // We need to go through the media textures one at a time to make sure that we have permission
                // to change them

                // FIXME: Race condition here since some other texture entry manipulator may overwrite/get
                // overwritten.  Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
                // directly.
                Primitive.TextureEntry te = part.Shape.Textures;

                lock (media)
                {
                    for (int i = 0; i < media.Count; i++)
                    {
                        if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i))
                        {
                            media[i] = omu.FaceMedia[i];

                            // When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal
                            // texture update, so we don't need to worry about clearing MediaFlags here.
                            if (null == media[i])
                            {
                                continue;
                            }

                            SetPartMediaFlags(part, i, true);

                            //                        MainConsole.Instance.DebugFormat(
                            //                            "[MOAP]: Media flags for face {0} is {1}",
                            //                            i, face.MediaFlags);
                            //                        MainConsole.Instance.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name);
                        }
                    }
                }

                part.Shape.Textures = te;

//                for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++)
//                    MainConsole.Instance.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]);
            }

            UpdateMediaUrl(part, agentId);

            // Arguably, we could avoid sending a full update to the avatar that just changed the texture.
            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);

            part.TriggerScriptChangedEvent(Changed.MEDIA);

            return(MainServer.BlankResponse);
        }
예제 #9
0
        /// <summary>
        /// This closes the scrpit, removes it from any known spots, and disposes of itself.
        /// </summary>
        /// <param name="Silent">Should we back up this script and fire state_exit?</param>
        public void CloseAndDispose(bool Silent)
        {
// this is still broken ?
            m_ScriptEngine.MaintenanceThread.RemoveFromEventSchQueue(this, true);

            if (!Silent)
            {
                if (Script != null)
                {
                    /*
                     * //Fire this directly so its not closed before its fired
                     * SetEventParams("state_exit", new DetectParams[0]);
                     *
                     * m_ScriptEngine.MaintenanceThread.ProcessQIS(new QueueItemStruct()
                     * {
                     *  ID = this,
                     *  CurrentlyAt = null,
                     *  functionName = "state_exit",
                     *  param = new object[0],
                     *  llDetectParams = new DetectParams[0],
                     *  VersionID = VersionID
                     * });
                     */
                    // dont think we should fire state_exit here
                    //                    m_ScriptEngine.MaintenanceThread.DoAndWaitEventSch(this, "state_exit",
                    //                        new DetectParams[0], VersionID, EventPriority.FirstStart, new object[0]);
                    m_ScriptEngine.StateSave.SaveStateTo(this);
                }
            }
            VersionID += 5;
            m_ScriptEngine.MaintenanceThread.SetEventSchSetIgnoreNew(this, false);

            //Give the user back any controls we took
            ReleaseControls();

            // Tell script not to accept new requests
            //These are fine to set as the state wont be saved again
            if (!Silent)
            {
                Running  = false;
                Disabled = true;
            }

            // Remove from internal structure
            ScriptEngine.ScriptProtection.RemoveScript(this);
//            if (!Silent) //Don't remove on a recompile because we'll make it under a different assembly
//                ScriptEngine.ScriptProtection.RemovePreviouslyCompiled(Source);

            //Remove any errors that might be sitting around
            m_ScriptEngine.ScriptErrorReporter.RemoveError(ItemID);

            #region Clean out script parts

            //Only if this script changed target omega do we reset it
            if (TargetOmegaWasSet)
            {
                Part.AngularVelocity = Vector3.Zero;                  // Removed in SL
                Part.ScheduleUpdate(PrimUpdateFlags.AngularVelocity); // Send changes to client.
            }

            #endregion

            if (Script != null)
            {
                // Stop long command on script
                m_ScriptEngine.RemoveScript(Part.UUID, ItemID);

                //Release the script and destroy it
                ILease lease = (ILease)RemotingServices.GetLifetimeService(Script as MarshalByRefObject);
                if (lease != null)
                {
                    lease.Unregister(Script.Sponsor);
                }

                Script.Close();
                Script = null;
            }

            if (AppDomain == null)
            {
                return;
            }

            // Tell AppDomain that we have stopped script
            m_ScriptEngine.AppDomainManager.UnloadScriptAppDomain(AppDomain);
            AppDomain = null;

            m_log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Closed Script " + InventoryItem.Name + " in " + Part.Name);
        }
예제 #10
0
        /// <summary>
        ///   Set the owner of the root part.
        /// </summary>
        /// <param name = "part"></param>
        /// <param name = "cAgentID"></param>
        /// <param name = "cGroupID"></param>
        public void SetRootPartOwner(ISceneChildEntity part, UUID cAgentID, UUID cGroupID)
        {
            part.LastOwnerID = part.OwnerID;
            part.OwnerID = cAgentID;
            part.GroupID = cGroupID;

            if (part.OwnerID != cAgentID)
            {
                // Apply Next Owner Permissions if we're not bypassing permissions
                if (!m_scene.Permissions.BypassPermissions())
                    ApplyNextOwnerPermissions();
            }

            part.ScheduleUpdate(PrimUpdateFlags.ForcedFullUpdate);
        }
예제 #11
0
        public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice)
        {
            ISceneChildEntity part = m_scene.GetSceneObjectPart(localID);

            if (part == null)
            {
                return(false);
            }

            if (part.ParentEntity == null)
            {
                return(false);
            }

            ISceneEntity       group           = part.ParentEntity;
            ILLClientInventory inventoryModule = m_scene.RequestModuleInterface <ILLClientInventory>();

            switch (saleType)
            {
            case 1:     // Sell as original (in-place sale)
                uint effectivePerms = group.GetEffectivePermissions();

                if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
                {
                    if (m_dialogModule != null)
                    {
                        m_dialogModule.SendAlertToUser(remoteClient, "This item doesn't appear to be for sale");
                    }
                    return(false);
                }

                group.SetOwnerId(remoteClient.AgentId);
                group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId);

                if (m_scene.Permissions.PropagatePermissions())
                {
                    foreach (ISceneChildEntity child in group.ChildrenEntities())
                    {
                        child.Inventory.ChangeInventoryOwner(remoteClient.AgentId);
                        child.TriggerScriptChangedEvent(Changed.OWNER);
                        child.ApplyNextOwnerPermissions();
                    }
                }

                part.ObjectSaleType = 0;
                part.SalePrice      = 10;

                group.HasGroupChanged = true;
                part.GetProperties(remoteClient);
                part.TriggerScriptChangedEvent(Changed.OWNER);
                group.ResumeScripts();
                part.ScheduleUpdate(PrimUpdateFlags.ForcedFullUpdate);

                break;

            case 2:     // Sell a copy
                Vector3 inventoryStoredPosition = new Vector3
                                                      (((group.AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX)
                              ? m_scene.RegionInfo.RegionSizeX - 1
                              : group.AbsolutePosition.X)
                                                      ,
                                                      (group.AbsolutePosition.X > m_scene.RegionInfo.RegionSizeY)
                             ? m_scene.RegionInfo.RegionSizeY - 1
                             : group.AbsolutePosition.X,
                                                      group.AbsolutePosition.Z);

                Vector3 originalPosition = group.AbsolutePosition;

                group.AbsolutePosition = inventoryStoredPosition;

                string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat((SceneObjectGroup)group);
                group.AbsolutePosition = originalPosition;

                uint perms = group.GetEffectivePermissions();

                if ((perms & (uint)PermissionMask.Transfer) == 0)
                {
                    if (m_dialogModule != null)
                    {
                        m_dialogModule.SendAlertToUser(remoteClient, "This item doesn't appear to be for sale");
                    }
                    return(false);
                }

                AssetBase asset = new AssetBase(UUID.Random(), part.Name,
                                                AssetType.Object, group.OwnerID)
                {
                    Description = part.Description, Data = Utils.StringToBytes(sceneObjectXml)
                };
                asset.ID = m_scene.AssetService.Store(asset);

                InventoryItemBase item = new InventoryItemBase
                {
                    CreatorId   = part.CreatorID.ToString(),
                    CreatorData = part.CreatorData,
                    ID          = UUID.Random(),
                    Owner       = remoteClient.AgentId,
                    AssetID     = asset.ID,
                    Description = asset.Description,
                    Name        = asset.Name,
                    AssetType   = asset.Type,
                    InvType     = (int)InventoryType.Object,
                    Folder      = categoryID
                };


                uint nextPerms = (perms & 7) << 13;
                if ((nextPerms & (uint)PermissionMask.Copy) == 0)
                {
                    perms &= ~(uint)PermissionMask.Copy;
                }
                if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
                {
                    perms &= ~(uint)PermissionMask.Transfer;
                }
                if ((nextPerms & (uint)PermissionMask.Modify) == 0)
                {
                    perms &= ~(uint)PermissionMask.Modify;
                }

                item.BasePermissions     = perms & part.NextOwnerMask;
                item.CurrentPermissions  = perms & part.NextOwnerMask;
                item.NextPermissions     = part.NextOwnerMask;
                item.EveryOnePermissions = part.EveryoneMask &
                                           part.NextOwnerMask;
                item.GroupPermissions = part.GroupMask &
                                        part.NextOwnerMask;
                item.CurrentPermissions |= 16;     // Slam!
                item.CreationDate        = Util.UnixTimeSinceEpoch();

                if (inventoryModule != null)
                {
                    if (inventoryModule.AddInventoryItem(item))
                    {
                        remoteClient.SendInventoryItemCreateUpdate(item, 0);
                    }
                    else
                    {
                        if (m_dialogModule != null)
                        {
                            m_dialogModule.SendAlertToUser(remoteClient,
                                                           "Cannot buy now. Your inventory is unavailable");
                        }
                        return(false);
                    }
                }
                break;

            case 3:     // Sell contents
                List <UUID> invList = part.Inventory.GetInventoryList();

#if (!ISWIN)
                bool okToSell = true;
                foreach (UUID invId in invList)
                {
                    TaskInventoryItem item1 = part.Inventory.GetInventoryItem(invId);
                    if ((item1.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
                    {
                        okToSell = false;
                        break;
                    }
                }
#else
                bool okToSell = invList.Select(invID => part.Inventory.GetInventoryItem(invID)).All(item1 => (item1.CurrentPermissions & (uint)PermissionMask.Transfer) != 0);
#endif

                if (!okToSell)
                {
                    if (m_dialogModule != null)
                    {
                        m_dialogModule.SendAlertToUser(
                            remoteClient, "This item's inventory doesn't appear to be for sale");
                    }
                    return(false);
                }

                if (invList.Count > 0)
                {
                    if (inventoryModule != null)
                    {
                        inventoryModule.MoveTaskInventoryItemsToUserInventory(remoteClient.AgentId, part.Name, part,
                                                                              invList);
                    }
                }
                break;
            }

            return(true);
        }
예제 #12
0
        public void PlayfwdState(ISceneChildEntity part)
        {
            if (part != null)
            {
                bool ChangedScale = false;
                bool ChangedRot = false;
                bool ChangedPos = false;
                part.Undoing = true;

                if (part.UUID == part.ParentEntity.UUID)
                {
                    if (Position != Vector3.Zero)
                    {
                        ChangedPos = true;
                        part.ParentEntity.AbsolutePosition = Position;
                    }
                    if (Rotation != Quaternion.Identity)
                    {
                        ChangedRot = true;
                        part.UpdateRotation(Rotation);
                    }
                    if (Scale != Vector3.Zero)
                    {
                        ChangedScale = true;
                        part.Resize(Scale);
                    }

                    foreach (
                        ISceneChildEntity child in
                            part.ParentEntity.ChildrenEntities().Where(child => child.UUID != part.UUID))
                    {
                        child.Redo(); //No updates here, child redo will do it on their own
                    }
                }
                else
                {
                    if (Position != Vector3.Zero)
                    {
                        ChangedPos = true;
                        part.FixOffsetPosition(Position, false);
                    }
                    if (Rotation != Quaternion.Identity)
                    {
                        ChangedRot = true;
                        part.ParentEntity.Rotation = (Rotation);
                    }
                    if (Scale != Vector3.Zero)
                    {
                        ChangedScale = true;
                        part.Resize(Scale);
                    }
                }

                part.ScheduleUpdate((ChangedScale ? PrimUpdateFlags.Shape : PrimUpdateFlags.None) |
                                    (ChangedPos ? PrimUpdateFlags.Position : PrimUpdateFlags.None) |
                                    (ChangedRot ? PrimUpdateFlags.Rotation : PrimUpdateFlags.None));
                part.Undoing = false;
            }
        }
예제 #13
0
        /// <summary>
        ///     This closes the scrpit, removes it from any known spots, and disposes of itself.
        /// </summary>
        /// <param name="shouldbackup">Should we back up this script and fire state_exit?</param>
        public void CloseAndDispose(bool shouldbackup)
        {
            m_ScriptEngine.MaintenanceThread.RemoveFromEventSchQueue(this, true);

            if (Script != null)
            {
                //Fire the exit event for scripts that support it
                Exception      ex;
                EnumeratorInfo info = null;
                while ((info = Script.ExecuteEvent(State, "exit", new object[0], info, out ex))
                       != null)
                {
                }
            }
            m_ScriptEngine.MaintenanceThread.SetEventSchSetIgnoreNew(this, false);

            //Give the user back any controls we took
            ReleaseControls();

            // Tell script not to accept new requests
            //These are fine to set as the state wont be saved again
            if (shouldbackup)
            {
                Running  = false;
                Disabled = true;
            }

            // Remove from internal structure
            ScriptEngine.ScriptProtection.RemoveScript(this);

            //Remove any errors that might be sitting around
            m_ScriptEngine.ScriptErrorReporter.RemoveError(ItemID);

            #region Clean out script parts

            //Only if this script changed target omega do we reset it
            if (TargetOmegaWasSet)
            {
                Part.AngularVelocity = Vector3.Zero;                  // Removed in SL
                Part.ScheduleUpdate(PrimUpdateFlags.AngularVelocity); // Send changes to client.
            }

            #endregion

            if (Script != null)
            {
                // Stop long command on script
                m_ScriptEngine.RemoveScriptFromPlugins(Part.UUID, ItemID);

                //Release the script and destroy it
                ILease lease = (ILease)RemotingServices.GetLifetimeService(Script as MarshalByRefObject);
                if (lease != null)
                {
                    lease.Unregister(Script.Sponsor);
                }

                Script.Close();
                Script = null;
            }

            if (InventoryItem != null && Part != null)
            {
                MainConsole.Instance.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Closed Script " +
                                           InventoryItem.Name + " in " +
                                           Part.Name);
            }
            if (AppDomain == null)
            {
                return;
            }

            // Tell AppDomain that we have stopped script
            m_ScriptEngine.AppDomainManager.UnloadScriptAppDomain(AppDomain);
            AppDomain = null;
        }
예제 #14
0
        public void SetMediaEntry (ISceneChildEntity part, int face, MediaEntry me)
        {
            CheckFaceParam(part, face);

            if (null == part.Shape.Media)
            {
                if (me == null)
                    return;
                else
                    part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
            }

            lock (part.Shape.Media)
                part.Shape.Media[face] = me;

            UpdateMediaUrl(part, UUID.Zero);

            SetPartMediaFlags(part, face, me != null);

            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
            part.TriggerScriptChangedEvent(Changed.MEDIA);
        }
예제 #15
0
파일: LSL_Api.cs 프로젝트: rknop/Aurora-Sim
        protected void SetScale(ISceneChildEntity part, LSL_Vector scale)
        {
            if (part == null || part.ParentEntity == null || part.ParentEntity.IsDeleted)
                return;

            IOpenRegionSettingsModule WSModule = m_host.ParentEntity.Scene.RequestModuleInterface<IOpenRegionSettingsModule> ();
            if (WSModule != null)
            {
                if (WSModule.MinimumPrimScale != -1)
                {
                    if (scale.x < WSModule.MinimumPrimScale)
                        scale.x = WSModule.MinimumPrimScale;
                    if (scale.y < WSModule.MinimumPrimScale)
                        scale.y = WSModule.MinimumPrimScale;
                    if (scale.z < WSModule.MinimumPrimScale)
                        scale.z = WSModule.MinimumPrimScale;
                }

                if (part.ParentEntity.RootChild.PhysActor != null && part.ParentEntity.RootChild.PhysActor.IsPhysical &&
                    WSModule.MaximumPhysPrimScale != -1)
                {
                    if (scale.x > WSModule.MaximumPhysPrimScale)
                        scale.x = WSModule.MaximumPhysPrimScale;
                    if (scale.y > WSModule.MaximumPhysPrimScale)
                        scale.y = WSModule.MaximumPhysPrimScale;
                    if (scale.z > WSModule.MaximumPhysPrimScale)
                        scale.z = WSModule.MaximumPhysPrimScale;
                }

                if (WSModule.MaximumPrimScale != -1)
                {
                    if (scale.x > WSModule.MaximumPrimScale)
                        scale.x = WSModule.MaximumPrimScale;
                    if (scale.y > WSModule.MaximumPrimScale)
                        scale.y = WSModule.MaximumPrimScale;
                    if (scale.z > WSModule.MaximumPrimScale)
                        scale.z = WSModule.MaximumPrimScale;
                }
            }

            Vector3 tmp = part.Scale;
            tmp.X = (float)scale.x;
            tmp.Y = (float)scale.y;
            tmp.Z = (float)scale.z;
            part.Scale = tmp;
            part.ScheduleUpdate(PrimUpdateFlags.FindBest);
        }
예제 #16
0
        /// <summary>
        /// Set a light point on a part
        /// </summary>
        /// FIXME: Much of this code should probably be in SceneObjectGroup
        ///
        /// <param name="part"></param>
        /// <param name="light"></param>
        /// <param name="color"></param>
        /// <param name="intensity"></param>
        /// <param name="radius"></param>
        /// <param name="falloff"></param>
        protected void SetPointLight (ISceneChildEntity part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
        {
            if (part == null)
                return;

            bool same = true;
            if (light)
            {
                if (part.Shape.LightEntry != true)
                    same = false;
                part.Shape.LightEntry = true;
                if (part.Shape.LightColorR != Util.Clip ((float)color.x, 0.0f, 1.0f))
                    same = false;
                part.Shape.LightColorR = Util.Clip ((float)color.x, 0.0f, 1.0f);
                if (part.Shape.LightColorG != Util.Clip ((float)color.y, 0.0f, 1.0f))
                    same = false;
                part.Shape.LightColorG = Util.Clip ((float)color.y, 0.0f, 1.0f);
                if (part.Shape.LightColorB != Util.Clip ((float)color.z, 0.0f, 1.0f))
                    same = false;
                part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
                if (part.Shape.LightIntensity != intensity)
                    same = false;
                part.Shape.LightIntensity = intensity;
                if (part.Shape.LightRadius != radius)
                    same = false;
                part.Shape.LightRadius = radius;
                if (part.Shape.LightFalloff != falloff)
                    same = false;
                part.Shape.LightFalloff = falloff;
            }
            else
            {
                if (part.Shape.LightEntry != false)
                    same = false;
                part.Shape.LightEntry = false;
            }

            if (!same)
            {
                part.ParentEntity.HasGroupChanged = true;
                part.ScheduleUpdate (PrimUpdateFlags.FindBest);
            }
        }
예제 #17
0
        /// <summary>
        /// Set flexi parameters of a part.
        ///
        /// FIXME: Much of this code should probably be within the part itself.
        /// </summary>
        /// <param name="part"></param>
        /// <param name="flexi"></param>
        /// <param name="softness"></param>
        /// <param name="gravity"></param>
        /// <param name="friction"></param>
        /// <param name="wind"></param>
        /// <param name="tension"></param>
        /// <param name="Force"></param>
        protected void SetFlexi (ISceneChildEntity part, bool flexi, int softness, float gravity, float friction,
            float wind, float tension, LSL_Vector Force)
        {
            if (part == null)
                return;

            if (flexi)
            {
                part.Shape.PathCurve |= (byte)Extrusion.Flexible;
                part.Shape.FlexiEntry = true;   // this setting flexi true isn't working, but the below parameters do
                // work once the prim is already flexi
                part.Shape.FlexiSoftness = softness;
                part.Shape.FlexiGravity = gravity;
                part.Shape.FlexiDrag = friction;
                part.Shape.FlexiWind = wind;
                part.Shape.FlexiTension = tension;
                part.Shape.FlexiForceX = (float)Force.x;
                part.Shape.FlexiForceY = (float)Force.y;
                part.Shape.FlexiForceZ = (float)Force.z;
                part.Shape.PathCurve = 0x80;
            }
            else
            {
                int curve = part.Shape.PathCurve;
                curve &= (int)(~(Extrusion.Flexible));
                part.Shape.PathCurve = (byte)curve;
                part.Shape.FlexiEntry = false;
            }


            part.ParentEntity.HasGroupChanged = true;
            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
        }
예제 #18
0
        public void SetMediaEntry(ISceneChildEntity part, int face, MediaEntry me)
        {
            CheckFaceParam(part, face);

            if (null == part.Shape.Media)
            {
                if (me == null)
                    return;
                else
                {
                    part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
                }
            }

            if (part.Shape.Media[face] == null) //If it doesn't exist, set the default parameters for it
                me.InteractPermissions = MediaPermission.All;
            lock (part.Shape.Media)
                part.Shape.Media[face] = me;

            UpdateMediaUrl(part, UUID.Zero);

            SetPartMediaFlags(part, face, me != null);

            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
            part.TriggerScriptChangedEvent(Changed.MEDIA);
        }
예제 #19
0
        /// <summary>
        ///     Received from the viewer if a user has changed the url of a media texture.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="path"></param>
        /// <param name="httpRequest"></param>
        /// <param name="httpResponse"></param>
        /// <returns></returns>
        protected byte[] HandleObjectMediaNavigateMessage(string path, Stream request, OSHttpRequest httpRequest,
                                                          OSHttpResponse httpResponse)
        {
//            MainConsole.Instance.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);

            OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(HttpServerHandlerHelpers.ReadFully(request));
            ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();

            omn.Deserialize(osd);

            UUID primId = omn.PrimID;

            ISceneChildEntity part = m_scene.GetSceneObjectPart(primId);

            if (null == part)
            {
                MainConsole.Instance.WarnFormat(
                    "[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
                    primId, m_scene.RegionInfo.RegionName);
                return(MainServer.BlankResponse);
            }

            UUID agentId = default(UUID);

            lock (m_omuCapUsers)
                agentId = m_omuCapUsers[path];

            if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
            {
                return(MainServer.BlankResponse);
            }

//            MainConsole.Instance.DebugFormat(
//                "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
//                omn.Face, part.Name, part.UUID, omn.URL);

            // If media has never been set for this prim, then just return.
            if (null == part.Shape.Media)
            {
                return(MainServer.BlankResponse);
            }

            MediaEntry me = null;

            lock (part.Shape.Media)
                me = part.Shape.Media[omn.Face];

            // Do the same if media has not been set up for a specific face
            if (null == me)
            {
                return(MainServer.BlankResponse);
            }

            if (me.EnableWhiteList)
            {
                if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
                {
//                    MainConsole.Instance.DebugFormat(
//                        "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
//                        omn.Face, part.Name, part.UUID, omn.URL);

                    return(MainServer.BlankResponse);
                }
            }

            me.CurrentURL = omn.URL;

            UpdateMediaUrl(part, agentId);

            part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);

            part.TriggerScriptChangedEvent(Changed.MEDIA);

            return(OSDParser.SerializeLLSDXmlBytes(new OSD()));
        }
예제 #20
0
파일: LSL_Api.cs 프로젝트: rknop/Aurora-Sim
        private void SetTextureAnim (ISceneChildEntity part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
        {

            Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
            pTexAnim.Flags = (Primitive.TextureAnimMode)mode;

            //ALL_SIDES
            if (face == ScriptBaseClass.ALL_SIDES)
                face = 255;

            pTexAnim.Face = (uint)face;
            pTexAnim.Length = (float)length;
            pTexAnim.Rate = (float)rate;
            pTexAnim.SizeX = (uint)sizex;
            pTexAnim.SizeY = (uint)sizey;
            pTexAnim.Start = (float)start;

            part.AddTextureAnimation(pTexAnim);
            part.ScheduleUpdate(PrimUpdateFlags.FindBest);
        }
예제 #21
0
        /// <summary>
        /// This closes the scrpit, removes it from any known spots, and disposes of itself.
        /// </summary>
        /// <param name="Silent">Should we back up this script and fire state_exit?</param>
        public void CloseAndDispose(bool Silent)
        {
            if (!Silent)
            {
                if (Script != null)
                {
                    m_ScriptEngine.StateSave.SaveStateTo(this);
                }
            }
            VersionID += 5;

            //Give the user back any controls we took
            ReleaseControls();

            // Tell script not to accept new requests
            //These are fine to set as the state wont be saved again
            if (!Silent)
            {
                Running  = false;
                Disabled = true;
            }

            // Remove from internal structure
            ScriptEngine.ScriptProtection.RemoveScript(this);
//            if (!Silent) //Don't remove on a recompile because we'll make it under a different assembly
//                ScriptEngine.ScriptProtection.RemovePreviouslyCompiled(Source);

            //Remove any errors that might be sitting around
            m_ScriptEngine.ScriptErrorReporter.RemoveError(ItemID);

            #region Clean out script parts

            //Only if this script changed target omega do we reset it
            if (TargetOmegaWasSet)
            {
                Part.AngularVelocity = Vector3.Zero;                  // Removed in SL
                Part.ScheduleUpdate(PrimUpdateFlags.AngularVelocity); // Send changes to client.
            }

            #endregion

            if (Script != null)
            {
                // Stop long command on script
                m_ScriptEngine.RemoveScript(Part.UUID, ItemID);

                //Release the script and destroy it
                ILease lease = (ILease)RemotingServices.GetLifetimeService(Script as MarshalByRefObject);
                if (lease != null)
                {
                    lease.Unregister(Script.Sponsor);
                }

                Script.Close();
                Script = null;
            }

            if (AppDomain != null)
            {
                // Tell AppDomain that we have stopped script
                m_ScriptEngine.AppDomainManager.UnloadScriptAppDomain(AppDomain);
                AppDomain = null;
            }

            m_log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Closed Script " + InventoryItem.Name + " in " + Part.Name);
        }
예제 #22
0
파일: LSL_Api.cs 프로젝트: rknop/Aurora-Sim
        private void SetParticleSystem (ISceneChildEntity part, LSL_List rules)
        {
            if (rules.Length == 0)
            {
                part.RemoveParticleSystem();
            }
            else
            {
                Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
                LSL_Vector tempv = new LSL_Vector();

                float tempf = 0;

                for (int i = 0; i < rules.Length; i += 2)
                {
                    LSL_Integer rule = rules.GetLSLIntegerItem(i);
                    if (rule == (int)ScriptBaseClass.PSYS_PART_FLAGS)
                    {
                        prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_START_COLOR)
                    {
                        tempv = rules.GetVector3Item(i + 1);
                        prules.PartStartColor.R = (float)tempv.x;
                        prules.PartStartColor.G = (float)tempv.y;
                        prules.PartStartColor.B = (float)tempv.z;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_START_ALPHA)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.PartStartColor.A = tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_END_COLOR)
                    {
                        tempv = rules.GetVector3Item(i + 1);
                        prules.PartEndColor.R = (float)tempv.x;
                        prules.PartEndColor.G = (float)tempv.y;
                        prules.PartEndColor.B = (float)tempv.z;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_END_ALPHA)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.PartEndColor.A = tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_START_SCALE)
                    {
                        tempv = rules.GetVector3Item(i + 1);
                        prules.PartStartScaleX = (float)tempv.x;
                        prules.PartStartScaleY = (float)tempv.y;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_END_SCALE)
                    {
                        tempv = rules.GetVector3Item(i + 1);
                        prules.PartEndScaleX = (float)tempv.x;
                        prules.PartEndScaleY = (float)tempv.y;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_PART_MAX_AGE)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.PartMaxAge = tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_ACCEL)
                    {
                        tempv = rules.GetVector3Item(i + 1);
                        prules.PartAcceleration.X = (float)tempv.x;
                        prules.PartAcceleration.Y = (float)tempv.y;
                        prules.PartAcceleration.Z = (float)tempv.z;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_PATTERN)
                    {
                        int tmpi = (int)rules.GetLSLIntegerItem(i + 1);
                        prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
                    }

                    // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The
                    // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
                    // client tells the difference between the two by looking at the 0x02 bit in
                    // the PartFlags variable.
                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_INNERANGLE)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.InnerAngle = (float)tempf;
                        prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.OuterAngle = (float)tempf;
                        prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_TEXTURE)
                    {
                        prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1));
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_RATE)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.BurstRate = (float)tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT)
                    {
                        prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.BurstRadius = (float)tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.BurstSpeedMin = (float)tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.BurstSpeedMax = (float)tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_MAX_AGE)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.MaxAge = (float)tempf;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY)
                    {
                        UUID key = UUID.Zero;
                        if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
                        {
                            prules.Target = key;
                        }
                        else
                        {
                            prules.Target = part.UUID;
                        }
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_OMEGA)
                    {
                        // AL: This is an assumption, since it is the only thing that would match.
                        tempv = rules.GetVector3Item(i + 1);
                        prules.AngularVelocity.X = (float)tempv.x;
                        prules.AngularVelocity.Y = (float)tempv.y;
                        prules.AngularVelocity.Z = (float)tempv.z;
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.InnerAngle = (float)tempf;
                        prules.PartFlags |= 0x02; // Set new angle format.
                    }

                    else if (rule == (int)ScriptBaseClass.PSYS_SRC_ANGLE_END)
                    {
                        tempf = (float)rules.GetLSLFloatItem(i + 1);
                        prules.OuterAngle = (float)tempf;
                        prules.PartFlags |= 0x02; // Set new angle format.
                    }
                }
                prules.CRC = 1;

                part.AddNewParticleSystem(prules);
            }
            part.ScheduleUpdate(PrimUpdateFlags.Particles);
        }
예제 #23
0
파일: LSL_Api.cs 프로젝트: rknop/Aurora-Sim
 protected void SetAlpha (ISceneChildEntity part, double alpha, int face)
 {
     Primitive.TextureEntry tex = part.Shape.Textures;
     Color4 texcolor;
     if (face >= 0 && face < GetNumberOfSides(part))
     {
         texcolor = tex.CreateFace((uint)face).RGBA;
         texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
         tex.FaceTextures[face].RGBA = texcolor;
         part.UpdateTexture(tex);
     }
     else if (face == ScriptBaseClass.ALL_SIDES)
     {
         for (int i = 0; i < GetNumberOfSides(part); i++)
         {
             if (tex.FaceTextures[i] != null)
             {
                 texcolor = tex.FaceTextures[i].RGBA;
                 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
                 tex.FaceTextures[i].RGBA = texcolor;
             }
         }
         texcolor = tex.DefaultTexture.RGBA;
         texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
         tex.DefaultTexture.RGBA = texcolor;
         part.UpdateTexture(tex);
     }
     part.ScheduleUpdate(PrimUpdateFlags.FullUpdate);
 }
예제 #24
0
        public void PlaybackState (ISceneChildEntity part)
        {
            if (part != null) {
                part.Undoing = true;

                bool ChangedScale = false;
                bool ChangedPos = false;

                if (part.UUID == part.ParentEntity.UUID) {
                    if (Position != Vector3.Zero) {
                        ChangedPos = true;
                        part.ParentEntity.AbsolutePosition = Position;
                    }
                    part.SetRotationOffset (true, Rotation, true);
                    if (Scale != Vector3.Zero) {
                        ChangedScale = true;
                        part.Scale = Scale;
                    }

                    foreach (
                        ISceneChildEntity child in
                            part.ParentEntity.ChildrenEntities ().Where (child => child.UUID != part.UUID)) {
                        child.Undo (); //No updates here, child undo will do it on their own
                    }
                } else {
                    if (Position != Vector3.Zero) {
                        ChangedPos = true;
                        part.FixOffsetPosition (Position, false);
                    }
                    part.UpdateRotation (Rotation);
                    if (Scale != Vector3.Zero) {
                        ChangedScale = true;
                        part.Resize (Scale);
                    }
                }
                part.Undoing = false;
                var updateFlags =
                    (ChangedScale ? PrimUpdateFlags.Shape : PrimUpdateFlags.None) |
                    (ChangedPos ? PrimUpdateFlags.Position : PrimUpdateFlags.None) |
                    PrimUpdateFlags.Rotation;

                part.ScheduleUpdate (updateFlags);
            }
        }