diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ClientManagerSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ClientManagerSyncModule.cs index ea6d8bb3e2..1e2dd6fee6 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ClientManagerSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ClientManagerSyncModule.cs @@ -85,7 +85,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation; //Register for Scene/SceneGraph events - m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ClientManager_OnObjectCreate); + //m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ClientManager_OnObjectCreate); + m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ClientManager_OnObjectCreateBySync); m_scene.EventManager.OnSymmetricSyncStop += ClientManager_OnSymmetricSyncStop; } @@ -151,7 +152,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// Script Engine's action upon an object is added to the local scene /// - private void ClientManager_OnObjectCreate(EntityBase entity) + private void ClientManager_OnObjectCreateBySync(EntityBase entity) { if (entity is SceneObjectGroup) { diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/PhysicsEngineSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/PhysicsEngineSyncModule.cs index e0b8c73982..757d6eb23f 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/PhysicsEngineSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/PhysicsEngineSyncModule.cs @@ -85,7 +85,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation; //Register for Scene/SceneGraph events - m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(PhysicsEngine_OnObjectCreate); + //m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(PhysicsEngine_OnObjectCreate); + m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(PhysicsEngine_OnObjectCreateBySync); m_scene.EventManager.OnSymmetricSyncStop += PhysicsEngine_OnSymmetricSyncStop; } @@ -151,7 +152,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// Script Engine's action upon an object is added to the local scene /// - private void PhysicsEngine_OnObjectCreate(EntityBase entity) + private void PhysicsEngine_OnObjectCreateBySync(EntityBase entity) { if (entity is SceneObjectGroup) { diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 1c17fd2f60..5f543ddf01 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -215,21 +215,27 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } - List primUpdates; - List presenceUpdates; + List primUpdates=null; + List presenceUpdates=null; - lock (m_updateSceneObjectPartLock) + if (m_primUpdates.Count > 0) { - primUpdates = new List(m_primUpdates.Values); - //presenceUpdates = new List(m_presenceUpdates.Values); - m_primUpdates.Clear(); - //m_presenceUpdates.Clear(); + lock (m_updateSceneObjectPartLock) + { + primUpdates = new List(m_primUpdates.Values); + //presenceUpdates = new List(m_presenceUpdates.Values); + m_primUpdates.Clear(); + //m_presenceUpdates.Clear(); + } } - lock (m_updateScenePresenceLock) + if (m_presenceUpdates.Count > 0) { - presenceUpdates = new List(m_presenceUpdates.Values); - m_presenceUpdates.Clear(); + lock (m_updateScenePresenceLock) + { + presenceUpdates = new List(m_presenceUpdates.Values); + m_presenceUpdates.Clear(); + } } // This could be another thread for sending outgoing messages or just have the Queue functions @@ -238,18 +244,23 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { // Dan's note: Sending the message when it's first queued would yield lower latency but much higher load on the simulator // as parts may be updated many many times very quickly. Need to implement a higher resolution send in heartbeat - foreach (SceneObjectGroup sog in primUpdates) + + if (primUpdates != null) { - //If this is a relay node, or at least one part of the object has the last update caused by this actor, then send the update - if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog))) + foreach (SceneObjectGroup sog in primUpdates) { - //send - string sogxml = SceneObjectSerializer.ToXml2Format(sog); - SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); - SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); + //If this is a relay node, or at least one part of the object has the last update caused by this actor, then send the update + if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog))) + { + //send + string sogxml = SceneObjectSerializer.ToXml2Format(sog); + SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); + SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); + } } } /* + if(presenceUpdates!=null){ foreach (ScenePresence presence in presenceUpdates) { try @@ -291,7 +302,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { m_log.ErrorFormat("[REGION SYNC MODULE] Caught exception sending presence updates for {0}: {1}", presence.Name, e.Message); } - } + }} * */ // Indicate that the current batch of updates has been completed @@ -415,6 +426,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet implemented."); } + //Object updates are sent by enqueuing into each connector's outQueue. private void SendObjectUpdateToRelevantSyncConnectors(SceneObjectGroup sog, SymmetricSyncMessage syncMsg) { List syncConnectors = GetSyncConnectorsForObjectUpdates(sog); @@ -427,6 +439,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + //Events are send out right away, without being put into the connector's outQueue first. + //May need a better method for managing the outgoing messages (i.e. prioritizing object updates and events) private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm) { List syncConnectors = GetSyncConnectorsForSceneEvents(init_actorID, rsm); @@ -784,8 +798,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } /// - /// This function will enqueue a message for each SyncConnector in the connector's outgoing queue. - /// Each SyncConnector has a SendLoop thread to send the messages in its outgoing queue. + /// This function will send out the sync message right away, without putting it into the SyncConnector's queue. + /// Should only be called for infrequent or high prority messages. /// /// /// diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs index f922b66980..69b3472728 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs @@ -82,7 +82,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation; //Register for Scene/SceneGraph events - m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate); + //m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate); + m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScenePersistence_OnObjectCreateBySync); } //Called after AddRegion() has been called for all region modules of the scene. @@ -156,12 +157,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// ScenePersistence's actions upon an object is added to the local scene. /// - private void ScenePersistence_OnObjectCreate(EntityBase entity) + private void ScenePersistence_OnObjectCreateBySync(EntityBase entity) { if (entity is SceneObjectGroup) { m_log.Warn(LogHeader + ": link to backup for " + entity.UUID); SceneObjectGroup sog = (SceneObjectGroup)entity; + + //probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true, + //then we do not need to worry about where an object is attach-to-backup and modify all those lines. + sog.AttachToBackup(); } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs index ee6ab985bc..e10292d5ec 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs @@ -84,14 +84,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation; //Register for Scene/SceneGraph events - m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScriptEngine_OnObjectCreate); + //m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScriptEngine_OnObjectCreate); + m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScriptEngine_OnObjectCreateBySync); m_scene.EventManager.OnSymmetricSyncStop += ScriptEngine_OnSymmetricSyncStop; //for local OnUpdateScript, we'll handle it the same way as a remove OnUpdateScript. //RegionSyncModule will capture a locally initiated OnUpdateScript event and publish it to other actors. m_scene.EventManager.OnNewScript += ScriptEngine_OnNewScript; - m_scene.EventManager.OnUpdateScript += ScriptEngine_OnUpdateScript; - //m_scene.EventManager.OnUpdateScriptBySync += ScriptEngine_OnUpdateScript; + m_scene.EventManager.OnUpdateScript += ScriptEngine_OnUpdateScript; + + m_scene.EventManager.OnAggregateScriptEvents += ScriptEngine_OnAggregateScriptEvents; LogHeader += "-" + m_actorID + "-" + m_scene.RegionInfo.RegionName; } @@ -166,7 +168,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// Script Engine's action upon an object is added to the local scene /// - private void ScriptEngine_OnObjectCreate(EntityBase entity) + private void ScriptEngine_OnObjectCreateBySync(EntityBase entity) { if (entity is SceneObjectGroup) { @@ -199,6 +201,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_scene.SymSync_OnUpdateScript(agentID, itemID, primID, isScriptRunning, newAssetID); } + public void ScriptEngine_OnAggregateScriptEvents(SceneObjectPart part) + { + part.aggregateScriptEvents(); + } + #endregion //ScriptEngineSyncModule } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 0d5d3a749e..d5f5cc93d3 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -2528,6 +2528,28 @@ namespace OpenSim.Region.Framework.Scenes } } + public delegate void AggregateScriptEvents(SceneObjectPart part); + public event AggregateScriptEvents OnAggregateScriptEvents; + public void TriggerAggregateScriptEvents(SceneObjectPart part) + { + AggregateScriptEvents handlerAggregateScriptEvents = OnAggregateScriptEvents; + if (handlerAggregateScriptEvents != null) + { + foreach (AggregateScriptEvents d in handlerAggregateScriptEvents.GetInvocationList()) + { + try + { + d(part); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerAggregateScriptEvents failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } //end of SYMMETRIC SYNC } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f9815ee8b6..99c150ff3c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -47,6 +47,11 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ObjectDeleteDelegate(EntityBase obj); + //SYMMETRIC SYNC + public delegate void ObjectCreateBySyncDelegate(EntityBase obj); + //end of SYMMETRIC SYNC + + /// /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components /// should be migrated out over time. @@ -64,6 +69,10 @@ namespace OpenSim.Region.Framework.Scenes public event ObjectCreateDelegate OnObjectCreate; public event ObjectDeleteDelegate OnObjectRemove; + //SYMMETRIC SYNC + public event ObjectCreateBySyncDelegate OnObjectCreateBySync; + //end of SYMMETRIC SYNC + #endregion #region Fields @@ -1963,9 +1972,8 @@ namespace OpenSim.Region.Framework.Scenes } } - //This is an object added due to receiving a state synchronization message from Scene or an actor. Do similar things as the original AddSceneObject(), - //but call ScheduleGroupForFullUpdate_TimeStampUnchanged() instead, so as not to modify the timestamp or actorID, since the object was not created - //locally. + //This is called when an object is added due to receiving a state synchronization message from Scene or an actor. Do similar things as the original AddSceneObject(), + //but call ScheduleGroupForFullUpdate_TimeStampUnchanged() instead, so as not to modify the timestamp or actorID, since the object was not created locally. public bool AddSceneObjectByStateSynch(SceneObjectGroup sceneObject) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) @@ -2007,8 +2015,12 @@ namespace OpenSim.Region.Framework.Scenes //if (attachToBackup) // sceneObject.AttachToBackup(); - if (OnObjectCreate != null) - OnObjectCreate(sceneObject); + //if (OnObjectCreate != null) + // OnObjectCreate(sceneObject); + + if (OnObjectCreateBySync != null) + OnObjectCreateBySync(sceneObject); + lock (SceneObjectGroupsByFullID) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index bb1669bb6f..fb6e231885 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4962,6 +4962,8 @@ namespace OpenSim.Region.Framework.Scenes } } + private Object propertyUpdateLock = new Object(); + //!!!!!! -- TODO: //!!!!!! -- We should call UpdateXXX functions to update each property, cause some of such updates involves sanity checking. public Scene.ObjectUpdateResult UpdateAllProperties(SceneObjectPart updatedPart) @@ -5005,72 +5007,96 @@ namespace OpenSim.Region.Framework.Scenes //Otherwise, our timestamp is less up to date, update the prim with the received copy Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Updated; + bool collisionSoundUpdated = false; + lock (propertyUpdateLock) + { - //See SceneObjectSerializer for the properties that are included in a serialized SceneObjectPart. - this.AllowedDrop = updatedPart.AllowedDrop; - this.CreatorID = updatedPart.CreatorID; - this.CreatorData = updatedPart.CreatorData; - this.FolderID = updatedPart.FolderID; - this.InventorySerial = updatedPart.InventorySerial; - this.TaskInventory = updatedPart.TaskInventory; - //Following two properties, UUID and LocalId, shall not be updated. - //this.UUID - //this.LocalId - this.Name = updatedPart.Name; - this.Material = updatedPart.Material; - this.PassTouches = updatedPart.PassTouches; - //RegionHandle shall not be copied, since updatedSog is sent by a different actor, which has a different local region - //this.RegionHandle - this.ScriptAccessPin = updatedPart.ScriptAccessPin; - this.GroupPosition = updatedPart.GroupPosition; - this.OffsetPosition = updatedPart.OffsetPosition; - this.RotationOffset = updatedPart.RotationOffset; - this.Velocity = updatedPart.Velocity; - this.AngularVelocity = updatedPart.AngularVelocity; - this.Acceleration = updatedPart.Acceleration; - this.Description = updatedPart.Description; - this.Color = updatedPart.Color; - this.Text = updatedPart.Text; - this.SitName = updatedPart.SitName; - this.TouchName = updatedPart.TouchName; - this.LinkNum = updatedPart.LinkNum; - this.ClickAction = updatedPart.ClickAction; - this.Shape = updatedPart.Shape; - this.Scale = updatedPart.Scale; - this.UpdateFlag = updatedPart.UpdateFlag; - this.SitTargetOrientation = updatedPart.SitTargetOrientation; - this.SitTargetPosition = updatedPart.SitTargetPosition; - this.SitTargetPositionLL = updatedPart.SitTargetPositionLL; - this.SitTargetOrientationLL = updatedPart.SitTargetOrientationLL; - //ParentID should still point to the rootpart in the local sog, do not update. If the root part changed, we will update it in SceneObjectGroup.UpdateObjectProperties() - //this.ParentID; - this.CreationDate = updatedPart.CreationDate; - this.Category = updatedPart.Category; - this.SalePrice = updatedPart.SalePrice; - this.ObjectSaleType = updatedPart.ObjectSaleType; - this.OwnershipCost = updatedPart.OwnershipCost; - this.GroupID = updatedPart.GroupID; - this.OwnerID = updatedPart.OwnerID; - this.LastOwnerID = updatedPart.LastOwnerID; - this.BaseMask = updatedPart.BaseMask; - this.OwnerMask = updatedPart.OwnerMask; - this.GroupMask = updatedPart.GroupMask; - this.EveryoneMask = updatedPart.EveryoneMask; - this.NextOwnerMask = updatedPart.NextOwnerMask; - this.Flags = updatedPart.Flags; - this.CollisionSound = updatedPart.CollisionSound; - this.CollisionSoundVolume = updatedPart.CollisionSoundVolume; - this.MediaUrl = updatedPart.MediaUrl; - this.TextureAnimation = updatedPart.TextureAnimation; - this.ParticleSystem = updatedPart.ParticleSystem; + //See SceneObjectSerializer for the properties that are included in a serialized SceneObjectPart. + this.AllowedDrop = updatedPart.AllowedDrop; + this.CreatorID = updatedPart.CreatorID; + this.CreatorData = updatedPart.CreatorData; + this.FolderID = updatedPart.FolderID; + this.InventorySerial = updatedPart.InventorySerial; + this.TaskInventory = updatedPart.TaskInventory; + //Following two properties, UUID and LocalId, shall not be updated. + //this.UUID + //this.LocalId + this.Name = updatedPart.Name; + this.Material = updatedPart.Material; + this.PassTouches = updatedPart.PassTouches; + //RegionHandle shall not be copied, since updatedSog is sent by a different actor, which has a different local region + //this.RegionHandle + this.ScriptAccessPin = updatedPart.ScriptAccessPin; + this.GroupPosition = updatedPart.GroupPosition; + this.OffsetPosition = updatedPart.OffsetPosition; + this.RotationOffset = updatedPart.RotationOffset; + this.Velocity = updatedPart.Velocity; + this.AngularVelocity = updatedPart.AngularVelocity; + this.Acceleration = updatedPart.Acceleration; + this.Description = updatedPart.Description; + this.Color = updatedPart.Color; + this.Text = updatedPart.Text; + this.SitName = updatedPart.SitName; + this.TouchName = updatedPart.TouchName; + this.LinkNum = updatedPart.LinkNum; + this.ClickAction = updatedPart.ClickAction; + this.Shape = updatedPart.Shape; + this.Scale = updatedPart.Scale; + this.UpdateFlag = updatedPart.UpdateFlag; + this.SitTargetOrientation = updatedPart.SitTargetOrientation; + this.SitTargetPosition = updatedPart.SitTargetPosition; + this.SitTargetPositionLL = updatedPart.SitTargetPositionLL; + this.SitTargetOrientationLL = updatedPart.SitTargetOrientationLL; + //ParentID should still point to the rootpart in the local sog, do not update. If the root part changed, we will update it in SceneObjectGroup.UpdateObjectProperties() + //this.ParentID; + this.CreationDate = updatedPart.CreationDate; + this.Category = updatedPart.Category; + this.SalePrice = updatedPart.SalePrice; + this.ObjectSaleType = updatedPart.ObjectSaleType; + this.OwnershipCost = updatedPart.OwnershipCost; + this.GroupID = updatedPart.GroupID; + this.OwnerID = updatedPart.OwnerID; + this.LastOwnerID = updatedPart.LastOwnerID; + this.BaseMask = updatedPart.BaseMask; + this.OwnerMask = updatedPart.OwnerMask; + this.GroupMask = updatedPart.GroupMask; + this.EveryoneMask = updatedPart.EveryoneMask; + this.NextOwnerMask = updatedPart.NextOwnerMask; + this.Flags = updatedPart.Flags; - //Update the timestamp and LastUpdatedByActorID first. - this.m_lastUpdateActorID = updatedPart.LastUpdateActorID; - this.m_lastUpdateTimeStamp = updatedPart.LastUpdateTimeStamp; + //We will update CollisionSound with special care so that it does not lead to ScheduleFullUpdate of this part, to make the actor think it just made an update and + //need to propogate that update to other actors. + //this.CollisionSound = updatedPart.CollisionSound; + collisionSoundUpdated = UpdateCollisionSound(updatedPart.CollisionSound); + + this.CollisionSoundVolume = updatedPart.CollisionSoundVolume; + this.MediaUrl = updatedPart.MediaUrl; + this.TextureAnimation = updatedPart.TextureAnimation; + this.ParticleSystem = updatedPart.ParticleSystem; + + //Update the timestamp and LastUpdatedByActorID first. + this.m_lastUpdateActorID = updatedPart.LastUpdateActorID; + this.m_lastUpdateTimeStamp = updatedPart.LastUpdateTimeStamp; + } + + if (collisionSoundUpdated) + { + m_parentGroup.Scene.EventManager.TriggerAggregateScriptEvents(this); + } return partUpdateResult; } + private bool UpdateCollisionSound(UUID updatedCollisionSound) + { + if (this.CollisionSound != updatedCollisionSound) + { + m_collisionSound = updatedCollisionSound; + return true; + } + return false; + } + /// /// Schedules this prim for a full update, without changing the timestamp or actorID (info on when and who modified any property). /// NOTE: this is the same as the original SceneObjectPart.ScheduleFullUpdate().