Added synchronization functions to RegionSyncModule, Scene, SceneGraph, SceneObjectGroup and
SceneObjectPart: examples: HandleAddOrUpdateObjectBySynchronization QueueSceneObjectPartForUpdate SceneObjectGroup.UpdateObjectAllProperties SceneObjectPart.UpdateAllProperties Now script engine and Scene can sync on script updating or Scene editing objects.dsg
							parent
							
								
									f10059ccd9
								
							
						
					
					
						commit
						384895cbdd
					
				|  | @ -170,32 +170,130 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|         // Lock is used to synchronize access to the update status and update queues |         // Lock is used to synchronize access to the update status and update queues | ||||||
|         private object m_updateSceneObjectPartLock = new object(); |         private object m_updateSceneObjectPartLock = new object(); | ||||||
|         private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>(); |         private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>(); | ||||||
|         private object m_updatePresenceLock = new object(); |         private object m_updateScenePresenceLock = new object(); | ||||||
|         private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>(); |         private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>(); | ||||||
|  |         private int m_sendingUpdates; | ||||||
| 
 | 
 | ||||||
|         public void QueueSceneObjectPartForUpdate(SceneObjectPart part) |         public void QueueSceneObjectPartForUpdate(SceneObjectPart part) | ||||||
|         { |         { | ||||||
|             lock (m_updateSceneObjectPartLock) |             //if the last update of the prim is caused by this actor itself, or if the actor is a relay node, then enqueue the update | ||||||
|  |             if (part.LastUpdateActorID.Equals(m_actorID) || m_isSyncRelay) | ||||||
|             { |             { | ||||||
|                 m_primUpdates[part.UUID] = part.ParentGroup; |                 lock (m_updateSceneObjectPartLock) | ||||||
|  |                 { | ||||||
|  |                     m_primUpdates[part.UUID] = part.ParentGroup; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void QueueScenePresenceForTerseUpdate(ScenePresence presence) |         public void QueueScenePresenceForTerseUpdate(ScenePresence presence) | ||||||
|         { |         { | ||||||
|             lock (m_updateSceneObjectPartLock) |             lock (m_updateScenePresenceLock) | ||||||
|             { |             { | ||||||
|                 m_presenceUpdates[presence.UUID] = presence; |                 m_presenceUpdates[presence.UUID] = presence; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public void SendObjectUpdates(List<SceneObjectGroup> sog) |         public void SendSceneUpdates() | ||||||
|         { |         { | ||||||
|  |             // Existing value of 1 indicates that updates are currently being sent so skip updates this pass | ||||||
|  |             if (Interlocked.Exchange(ref m_sendingUpdates, 1) == 1) | ||||||
|  |             { | ||||||
|  |                 m_log.WarnFormat("[REGION SYNC SERVER MODULE] SendUpdates(): An update thread is already running."); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|  |             List<SceneObjectGroup> primUpdates; | ||||||
|  |             List<ScenePresence> presenceUpdates; | ||||||
|  | 
 | ||||||
|  |             lock (m_updateSceneObjectPartLock) | ||||||
|  |             { | ||||||
|  |                 primUpdates = new List<SceneObjectGroup>(m_primUpdates.Values); | ||||||
|  |                 //presenceUpdates = new List<ScenePresence>(m_presenceUpdates.Values); | ||||||
|  |                 m_primUpdates.Clear(); | ||||||
|  |                 //m_presenceUpdates.Clear(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             lock (m_updateScenePresenceLock) | ||||||
|  |             { | ||||||
|  |                 presenceUpdates = new List<ScenePresence>(m_presenceUpdates.Values); | ||||||
|  |                 m_presenceUpdates.Clear(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // This could be another thread for sending outgoing messages or just have the Queue functions | ||||||
|  |             // create and queue the messages directly into the outgoing server thread. | ||||||
|  |             System.Threading.ThreadPool.QueueUserWorkItem(delegate | ||||||
|  |             { | ||||||
|  |                 // 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 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 || CheckObjectForSendingUpdate(sog)) | ||||||
|  |                     { | ||||||
|  |                         //send  | ||||||
|  |                         List<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog); | ||||||
|  | 
 | ||||||
|  |                         foreach (SyncConnector connector in syncConnectors) | ||||||
|  |                         { | ||||||
|  |                             string sogxml = SceneObjectSerializer.ToXml2Format(sog); | ||||||
|  |                             SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); | ||||||
|  |                             connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes()); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 /* | ||||||
|  |                 foreach (ScenePresence presence in presenceUpdates) | ||||||
|  |                 { | ||||||
|  |                     try | ||||||
|  |                     { | ||||||
|  |                         if (!presence.IsDeleted) | ||||||
|  |                         { | ||||||
|  |                              | ||||||
|  |                             OSDMap data = new OSDMap(10); | ||||||
|  |                             data["id"] = OSD.FromUUID(presence.UUID); | ||||||
|  |                             // Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers | ||||||
|  |                             if(presence.AbsolutePosition.IsFinite()) | ||||||
|  |                                 data["pos"] = OSD.FromVector3(presence.AbsolutePosition); | ||||||
|  |                             else | ||||||
|  |                                 data["pos"] = OSD.FromVector3(Vector3.Zero); | ||||||
|  |                             if(presence.Velocity.IsFinite()) | ||||||
|  |                                 data["vel"] = OSD.FromVector3(presence.Velocity); | ||||||
|  |                             else | ||||||
|  |                                 data["vel"] = OSD.FromVector3(Vector3.Zero); | ||||||
|  |                             data["rot"] = OSD.FromQuaternion(presence.Rotation); | ||||||
|  |                             data["fly"] = OSD.FromBoolean(presence.Flying); | ||||||
|  |                             data["flags"] = OSD.FromUInteger((uint)presence.AgentControlFlags); | ||||||
|  |                             data["anim"] = OSD.FromString(presence.Animator.CurrentMovementAnimation); | ||||||
|  |                             // needed for a full update | ||||||
|  |                             if (presence.ParentID != presence.lastSentParentID) | ||||||
|  |                             { | ||||||
|  |                                 data["coll"] = OSD.FromVector4(presence.CollisionPlane); | ||||||
|  |                                 data["off"] = OSD.FromVector3(presence.OffsetPosition); | ||||||
|  |                                 data["pID"] = OSD.FromUInteger(presence.ParentID); | ||||||
|  |                                 presence.lastSentParentID = presence.ParentID; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedAvatar, OSDParser.SerializeJsonString(data)); | ||||||
|  |                             m_server.EnqueuePresenceUpdate(presence.UUID, rsm.ToBytes()); | ||||||
|  |                             | ||||||
|  | 
 | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     catch (Exception e) | ||||||
|  |                     { | ||||||
|  |                         m_log.ErrorFormat("[REGION SYNC SERVER MODULE] Caught exception sending presence updates for {0}: {1}", presence.Name, e.Message); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                  * */ | ||||||
|  | 
 | ||||||
|  |                 // Indicate that the current batch of updates has been completed | ||||||
|  |                 Interlocked.Exchange(ref m_sendingUpdates, 0); | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         #endregion //IRegionSyncModule   |         #endregion //IRegionSyncModule   | ||||||
| 
 | 
 | ||||||
|         #region ICommandableModule Members |         #region ICommandableModule Members | ||||||
|  | @ -296,6 +394,60 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|             m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet implemented."); |             m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet implemented."); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Check if we need to send out an update message for the given object. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="sog"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         private bool CheckObjectForSendingUpdate(SceneObjectGroup sog) | ||||||
|  |         { | ||||||
|  |             if (sog == null || sog.IsDeleted) | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |             //If any part in the object has the last update caused by this actor itself, then send the update | ||||||
|  |             foreach (SceneObjectPart part in sog.Parts) | ||||||
|  |             { | ||||||
|  |                 if (part.LastUpdateActorID.Equals(m_actorID)) | ||||||
|  |                 { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Get the set of SyncConnectors to send updates of the given object.  | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="sog"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         private List<SyncConnector> GetSyncConnectorsForObjectUpdates(SceneObjectGroup sog) | ||||||
|  |         { | ||||||
|  |             List<SyncConnector> syncConnectors = new List<SyncConnector>(); | ||||||
|  |             if (m_isSyncRelay) | ||||||
|  |             { | ||||||
|  |                 //This is a relay node in the synchronization overlay, forward it to all connectors.  | ||||||
|  |                 //Note LastUpdateTimeStamp and LastUpdateActorID is one per SceneObjectPart, not one per SceneObjectGroup,  | ||||||
|  |                 //hence an actor sending in an update on one SceneObjectPart of a SceneObjectGroup may need to know updates | ||||||
|  |                 //in other parts as well, so we are sending to all connectors. | ||||||
|  |                 ForEachSyncConnector(delegate(SyncConnector connector) | ||||||
|  |                 { | ||||||
|  |                     syncConnectors.Add(connector); | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 //This is a end node in the synchronization overlay (e.g. a non ScenePersistence actor). Get the right set of synconnectors. | ||||||
|  |                 //This may go more complex when an actor connects to several ScenePersistence actors. | ||||||
|  |                 ForEachSyncConnector(delegate(SyncConnector connector) | ||||||
|  |                 { | ||||||
|  |                     syncConnectors.Add(connector); | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return syncConnectors; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         //NOTE: We proably don't need to do this, and there might not be a need for OnPostSceneCreation event to let RegionSyncModule |         //NOTE: We proably don't need to do this, and there might not be a need for OnPostSceneCreation event to let RegionSyncModule | ||||||
|         //      and ActorSyncModules to gain some access to each other. We'll keep it here for a while, until we are sure it's not  |         //      and ActorSyncModules to gain some access to each other. We'll keep it here for a while, until we are sure it's not  | ||||||
|         //      needed. |         //      needed. | ||||||
|  | @ -526,7 +678,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|             List<SyncConnector> closed = null; |             List<SyncConnector> closed = null; | ||||||
|             foreach (SyncConnector syncConnector in m_syncConnectors) |             foreach (SyncConnector syncConnector in m_syncConnectors) | ||||||
|             { |             { | ||||||
|                 // If connected, send the message. |                 // If connected, apply the action | ||||||
|                 if (syncConnector.Connected) |                 if (syncConnector.Connected) | ||||||
|                 { |                 { | ||||||
|                     action(syncConnector); |                     action(syncConnector); | ||||||
|  | @ -584,22 +736,50 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|                 case SymmetricSyncMessage.MsgType.NewObject: |                 case SymmetricSyncMessage.MsgType.NewObject: | ||||||
|  |                 case SymmetricSyncMessage.MsgType.UpdatedObject: | ||||||
|                     { |                     { | ||||||
|                         string sogxml = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); |                         HandleAddOrUpdateObjectBySynchronization(msg); | ||||||
|                          |                         //HandleAddNewObject(sog); | ||||||
|                         //m_log.Debug(LogHeader + ": " + sogxml); |                         return; | ||||||
| 
 |  | ||||||
|                         SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); |  | ||||||
| 
 |  | ||||||
|                         //HandleAddOrUpdateObjectInLocalScene(sog, true, true); |  | ||||||
|                         HandleAddNewObject(sog); |  | ||||||
|                     } |                     } | ||||||
|                     return; |  | ||||||
|                 default: |                 default: | ||||||
|                     return; |                     return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         public void HandleAddOrUpdateObjectBySynchronization(SymmetricSyncMessage msg) | ||||||
|  |         { | ||||||
|  |             string sogxml = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); | ||||||
|  |             SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); | ||||||
|  | 
 | ||||||
|  |             if (sog.IsDeleted) | ||||||
|  |             { | ||||||
|  |                 SymmetricSyncMessage.HandleTrivial(LogHeader, msg, String.Format("Ignoring update on deleted object, UUID: {0}.", sog.UUID)); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Scene.ObjectUpdateResult updateResult = m_scene.AddOrUpdateObjectBySynchronization(sog); | ||||||
|  | 
 | ||||||
|  |                 //if (added) | ||||||
|  |                 switch (updateResult) | ||||||
|  |                 { | ||||||
|  |                     case Scene.ObjectUpdateResult.New: | ||||||
|  |                         m_log.DebugFormat("[{0} Object \"{1}\" ({1}) ({2}) added.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString()); | ||||||
|  |                         break; | ||||||
|  |                     case Scene.ObjectUpdateResult.Updated: | ||||||
|  |                         m_log.DebugFormat("[{0} Object \"{1}\" ({1}) ({2}) updated.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString()); | ||||||
|  |                         break; | ||||||
|  |                     case Scene.ObjectUpdateResult.Error: | ||||||
|  |                         m_log.WarnFormat("[{0} Object \"{1}\" ({1}) ({2}) -- add or update ERROR.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString()); | ||||||
|  |                         break; | ||||||
|  |                     case Scene.ObjectUpdateResult.Unchanged: | ||||||
|  |                         m_log.DebugFormat("[{0} Object \"{1}\" ({1}) ({2}) unchanged after receiving an update.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString()); | ||||||
|  |                         break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         private void HandleAddNewObject(SceneObjectGroup sog) |         private void HandleAddNewObject(SceneObjectGroup sog) | ||||||
|         { |         { | ||||||
|             //RegionSyncModule only add object to SceneGraph. Any actor specific actions will be implemented  |             //RegionSyncModule only add object to SceneGraph. Any actor specific actions will be implemented  | ||||||
|  |  | ||||||
|  | @ -21,61 +21,22 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|         public enum MsgType |         public enum MsgType | ||||||
|         { |         { | ||||||
|             Null, |             Null, | ||||||
|             //ConnectSyncClient, |             // Actor -> SIM(Scene) | ||||||
|             //DisconnectSyncClient, |  | ||||||
|             // CM -> SIM(Scene) |  | ||||||
|             ActorConnect, |  | ||||||
|             AgentAdd, |  | ||||||
|             AgentUpdate, |  | ||||||
|             AgentRemove, |  | ||||||
|             AgentRequestSit, |  | ||||||
|             AgentSit, |  | ||||||
|             GrabObject, |  | ||||||
|             GrabUpdate, |  | ||||||
|             DeGrabObject, |  | ||||||
|             StartAnim, |  | ||||||
|             StopAnim, |  | ||||||
|             GetTerrain, |             GetTerrain, | ||||||
|             GetObjects, |             GetObjects, | ||||||
|             SubscribeObjects, |              | ||||||
|             GetAvatars, |  | ||||||
|             SubscribeAvatars, |  | ||||||
|             ChatFromClient, |  | ||||||
|             AvatarTeleportOut, // An LLClientView (real client) was converted to a RegionSyncAvatar |  | ||||||
|             AvatarTeleportIn,  // A RegionSyncAvatar was converted to an LLClientView (real client) |  | ||||||
|             // SIM -> CM |             // SIM -> CM | ||||||
|             Terrain, |             Terrain, | ||||||
|             NewObject,       // objects |             NewObject,       // objects | ||||||
|             UpdatedObject,   // objects |             UpdatedObject,   // objects | ||||||
|             RemovedObject,   // objects |             RemovedObject,   // objects | ||||||
|             NewAvatar,       // avatars |  | ||||||
|             UpdatedAvatar,   // avatars |  | ||||||
|             AnimateAvatar, |  | ||||||
|             AvatarAppearance, |  | ||||||
|             RemovedAvatar,   // avatars |  | ||||||
|             BalanceClientLoad, // Tells CM a client load target and a place to teleport the extras |  | ||||||
|             ChatFromSim, |  | ||||||
|             SitResponse, |  | ||||||
|             SendAnimations, |  | ||||||
|             // BIDIR |  | ||||||
|             EchoRequest, |  | ||||||
|             EchoResponse, |  | ||||||
|             RegionName, |  | ||||||
|             RegionStatus, |  | ||||||
|             //Added by KittyL |  | ||||||
|             // Actor -> Scene |  | ||||||
|             // ActorType, //to register the type (e.g. Client Manager or Script Engine) with Scene when sync channel is initialized |  | ||||||
|             //SetObjectProperty, |  | ||||||
|             // ActorStop, |  | ||||||
|             ResetScene, |  | ||||||
|             OnRezScript, |  | ||||||
|             OnScriptReset, |  | ||||||
|             OnUpdateScript, |  | ||||||
|             //QuarkSubscription, |  | ||||||
| 
 | 
 | ||||||
|             // Scene -> Script Engine |             // BIDIR | ||||||
|             //NewObjectWithScript, |             //EchoRequest, | ||||||
|             //SceneLocation, |             //EchoResponse, | ||||||
|  |             RegionName, | ||||||
|  |             //RegionStatus, | ||||||
|  |             ActorID, | ||||||
|         } |         } | ||||||
|         #endregion |         #endregion | ||||||
| 
 | 
 | ||||||
|  | @ -164,27 +125,27 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|         #endregion |         #endregion | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         public static void HandleSuccess(string header, RegionSyncMessage msg, string message) |         public static void HandleSuccess(string header, SymmetricSyncMessage msg, string message) | ||||||
|         { |         { | ||||||
|             m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message); |             m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static void HandleTrivial(string header, RegionSyncMessage msg, string message) |         public static void HandleTrivial(string header, SymmetricSyncMessage msg, string message) | ||||||
|         { |         { | ||||||
|             m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message); |             m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static void HandleWarning(string header, RegionSyncMessage msg, string message) |         public static void HandleWarning(string header, SymmetricSyncMessage msg, string message) | ||||||
|         { |         { | ||||||
|             m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message); |             m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static void HandleError(string header, RegionSyncMessage msg, string message) |         public static void HandleError(string header, SymmetricSyncMessage msg, string message) | ||||||
|         { |         { | ||||||
|             m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message); |             m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool HandlerDebug(string header, RegionSyncMessage msg, string message) |         public static bool HandlerDebug(string header, SymmetricSyncMessage msg, string message) | ||||||
|         { |         { | ||||||
|             m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message); |             m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message); | ||||||
|             return true; |             return true; | ||||||
|  |  | ||||||
|  | @ -45,6 +45,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|             get { return m_connectorNum; } |             get { return m_connectorNum; } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         //the actorID of the other end of the connection | ||||||
|  |         private string m_syncOtherSideActorID; | ||||||
|  |         public string OtherSideActorID | ||||||
|  |         { | ||||||
|  |             get { return m_syncOtherSideActorID; } | ||||||
|  |             set { m_syncOtherSideActorID = value; } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         //The region name of the other side of the connection |         //The region name of the other side of the connection | ||||||
|         private string m_syncOtherSideRegionName=""; |         private string m_syncOtherSideRegionName=""; | ||||||
|         public string OtherSideRegionName |         public string OtherSideRegionName | ||||||
|  | @ -267,6 +275,17 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule | ||||||
|                         m_log.DebugFormat("Syncing to region \"{0}\"", m_syncOtherSideRegionName);  |                         m_log.DebugFormat("Syncing to region \"{0}\"", m_syncOtherSideRegionName);  | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|  |                 case SymmetricSyncMessage.MsgType.ActorID: | ||||||
|  |                     { | ||||||
|  |                         m_syncOtherSideActorID = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); | ||||||
|  |                         if (m_regionSyncModule.IsSyncRelay) | ||||||
|  |                         { | ||||||
|  |                             SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.ActorID, m_regionSyncModule.ActorID); | ||||||
|  |                             Send(outMsg); | ||||||
|  |                         } | ||||||
|  |                         m_log.DebugFormat("Syncing to actor \"{0}\"", m_syncOtherSideActorID); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|                 default: |                 default: | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -598,6 +598,29 @@ namespace OpenSim.Region.Framework.Scenes | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         //This enumeration would help to identify if after a NewObject/UpdatedObject message is received, | ||||||
|  |         //the object is a new object and hence added to the scene graph, or it an object with some properties | ||||||
|  |         //just updated, or the copy of the object in the UpdatedObject message is the same with local copy  | ||||||
|  |         //(before we add time-stamp to identify updates from different actors/scene, it could be possible the same | ||||||
|  |         //update be forwarded, say from script engine to scene, and then back to script engine. | ||||||
|  |         public enum ObjectUpdateResult | ||||||
|  |         { | ||||||
|  |             New, //the New/UpdatedObject message ends up adding a new object to local scene graph | ||||||
|  |             Updated, //the object has some property updated after processing the New/UpdatedObject  | ||||||
|  |             Unchanged, //no property of the object has been changed after processing the New/UpdatedObject  | ||||||
|  |             //(it probably is the same update this end has sent out before | ||||||
|  |             Error //Errors happen during processing the message, e.g. the entity with the given UUID is not of type SceneObjectGroup  | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //This function should only be called by an actor who's local Scene is just a cache of the authorative Scene. | ||||||
|  |         //If the object already exists, use the new copy to replace it. | ||||||
|  |         //Return true if added, false if just updated | ||||||
|  |         public ObjectUpdateResult AddOrUpdateObjectBySynchronization(SceneObjectGroup sog) | ||||||
|  |         { | ||||||
|  |             return m_sceneGraph.AddOrUpdateObjectBySynchronization(sog); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|         #endregion //SYMMETRIC SYNC |         #endregion //SYMMETRIC SYNC | ||||||
| 
 | 
 | ||||||
|         public ICapabilitiesModule CapsModule |         public ICapabilitiesModule CapsModule | ||||||
|  | @ -1484,24 +1507,14 @@ namespace OpenSim.Region.Framework.Scenes | ||||||
|                         m_regionSyncServerModule.SendUpdates(); |                         m_regionSyncServerModule.SendUpdates(); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     /* |                     //SYMMETRIC SYNC | ||||||
|                     // The authoritative sim should not try to send coarse locations | 
 | ||||||
|                     // Leave this up to the client managers |                     //NOTE: If it is configured as symmetric sync in opensim.ini, the above IsSyncedServer() or IsSyncedClient() should all return false | ||||||
|                     if (!IsSyncedServer()) |                     if (RegionSyncModule != null) | ||||||
|                     { |                     { | ||||||
|                         if (m_frame % m_update_coarse_locations == 0) |                         RegionSyncModule.SendSceneUpdates(); | ||||||
|                         { |  | ||||||
|                             List<Vector3> coarseLocations; |  | ||||||
|                             List<UUID> avatarUUIDs; |  | ||||||
|                             SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); |  | ||||||
|                             // Send coarse locations to clients  |  | ||||||
|                             ForEachScenePresence(delegate(ScenePresence presence) |  | ||||||
|                             { |  | ||||||
|                                 presence.SendCoarseLocations(coarseLocations, avatarUUIDs); |  | ||||||
|                             }); |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                      * */ |                     //end of SYMMETRIC SYNC | ||||||
| 
 | 
 | ||||||
|                     int tmpPhysicsMS2 = Util.EnvironmentTickCount(); |                     int tmpPhysicsMS2 = Util.EnvironmentTickCount(); | ||||||
|                     // Do not simulate physics locally if this is a synced client |                     // Do not simulate physics locally if this is a synced client | ||||||
|  |  | ||||||
|  | @ -1920,10 +1920,105 @@ namespace OpenSim.Region.Framework.Scenes | ||||||
| 
 | 
 | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|              | 
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         #endregion |         #endregion // REGION SYNC | ||||||
| 
 | 
 | ||||||
|  |         #region SYMMETRIC SYNC | ||||||
|  | 
 | ||||||
|  |         public Scene.ObjectUpdateResult AddOrUpdateObjectBySynchronization(SceneObjectGroup updatedSog) | ||||||
|  |         { | ||||||
|  |             UUID sogID = updatedSog.UUID; | ||||||
|  | 
 | ||||||
|  |             if (Entities.ContainsKey(sogID)) | ||||||
|  |             { | ||||||
|  |                 //update the object | ||||||
|  |                 EntityBase entity = Entities[sogID]; | ||||||
|  |                 if (entity is SceneObjectGroup) | ||||||
|  |                 { | ||||||
|  |                     SceneObjectGroup localSog = (SceneObjectGroup)entity; | ||||||
|  |                     Scene.ObjectUpdateResult updateResult = localSog.UpdateObjectAllProperties(updatedSog); | ||||||
|  |                     return updateResult; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     m_log.Warn("Entity with " + sogID + " is not of type SceneObjectGroup"); | ||||||
|  |                     //return false; | ||||||
|  |                     return Scene.ObjectUpdateResult.Error; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 AddSceneObjectByStateSynch(updatedSog); | ||||||
|  |                 return Scene.ObjectUpdateResult.New; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //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. | ||||||
|  |         protected bool AddSceneObjectByStateSynch(SceneObjectGroup sceneObject) | ||||||
|  |         { | ||||||
|  |             if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |             if (Entities.ContainsKey(sceneObject.UUID)) | ||||||
|  |                 return false; | ||||||
|  | 
 | ||||||
|  |             SceneObjectPart[] children = sceneObject.Parts; | ||||||
|  | 
 | ||||||
|  |             // Clamp child prim sizes and add child prims to the m_numPrim count | ||||||
|  |             if (m_parentScene.m_clampPrimSize) | ||||||
|  |             { | ||||||
|  |                 foreach (SceneObjectPart part in children) | ||||||
|  |                 { | ||||||
|  |                     Vector3 scale = part.Shape.Scale; | ||||||
|  | 
 | ||||||
|  |                     if (scale.X > m_parentScene.m_maxNonphys) | ||||||
|  |                         scale.X = m_parentScene.m_maxNonphys; | ||||||
|  |                     if (scale.Y > m_parentScene.m_maxNonphys) | ||||||
|  |                         scale.Y = m_parentScene.m_maxNonphys; | ||||||
|  |                     if (scale.Z > m_parentScene.m_maxNonphys) | ||||||
|  |                         scale.Z = m_parentScene.m_maxNonphys; | ||||||
|  | 
 | ||||||
|  |                     part.Shape.Scale = scale; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             m_numPrim += children.Length; | ||||||
|  | 
 | ||||||
|  |             sceneObject.AttachToScene(m_parentScene); | ||||||
|  | 
 | ||||||
|  |             //SYMMETRIC SYNC,  | ||||||
|  |             sceneObject.ScheduleGroupForFullUpdate_SyncInfoUnchanged(); | ||||||
|  |             //end of SYMMETRIC SYNC,  | ||||||
|  | 
 | ||||||
|  |             Entities.Add(sceneObject); | ||||||
|  | 
 | ||||||
|  |             //ScenePersistenceSyncModule will attach the object to backup when it catches the OnObjectCreate event. | ||||||
|  |             //if (attachToBackup) | ||||||
|  |             //    sceneObject.AttachToBackup(); | ||||||
|  | 
 | ||||||
|  |             if (OnObjectCreate != null) | ||||||
|  |                 OnObjectCreate(sceneObject); | ||||||
|  | 
 | ||||||
|  |             lock (SceneObjectGroupsByFullID) | ||||||
|  |             { | ||||||
|  |                 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; | ||||||
|  |                 foreach (SceneObjectPart part in children) | ||||||
|  |                     SceneObjectGroupsByFullID[part.UUID] = sceneObject; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             lock (SceneObjectGroupsByLocalID) | ||||||
|  |             { | ||||||
|  |                 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; | ||||||
|  |                 foreach (SceneObjectPart part in children) | ||||||
|  |                     SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion //SYMMETRIC SYNC | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3459,6 +3459,141 @@ namespace OpenSim.Region.Framework.Scenes | ||||||
| 
 | 
 | ||||||
|         #region SYMMETRIC SYNC |         #region SYMMETRIC SYNC | ||||||
| 
 | 
 | ||||||
|  |         //update the existing copy of the object with updated properties in 'updatedSog' | ||||||
|  |         //NOTE: updates on script content are handled seperately (e.g. user edited the script and saved it) -- SESyncServerOnUpdateScript(), a handler of EventManager.OnUpdateScript         | ||||||
|  |         //public void UpdateObjectProperties(SceneObjectGroup updatedSog) | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Update the existing copy of the object with updated properties in 'updatedSog'. For now we update  | ||||||
|  |         /// all properties. Later on this should be edited to allow only updating a bucket of properties. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="updatedSog"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public Scene.ObjectUpdateResult UpdateObjectAllProperties(SceneObjectGroup updatedSog) | ||||||
|  |         { | ||||||
|  |             if (!this.GroupID.Equals(updatedSog.GroupID)) | ||||||
|  |                 return Scene.ObjectUpdateResult.Error; | ||||||
|  | 
 | ||||||
|  |             //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |             //NOTE!!!  | ||||||
|  |             //We do not want to simply call SceneObjectGroup.Copy here to clone the object:  | ||||||
|  |             //the prims (SceneObjectParts) in updatedSog are different instances than those in the local copy, | ||||||
|  |             //and we want to preserve the references to the prims in this local copy, especially for scripts  | ||||||
|  |             //of each prim, where the scripts have references to the local copy. If the local copy is replaced, | ||||||
|  |             //the prims (parts) will be replaces and we need to update all the references that were pointing to  | ||||||
|  |             //the previous prims. | ||||||
|  |             //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 
 | ||||||
|  |             Scene.ObjectUpdateResult groupUpdateResult = Scene.ObjectUpdateResult.Unchanged; | ||||||
|  |             Dictionary<UUID, SceneObjectPart> updatedParts = new Dictionary<UUID, SceneObjectPart>(); | ||||||
|  |             bool partsRemoved = false; //has any old part been removed? | ||||||
|  |             bool rootPartChanged = false; //has the rootpart be changed to a different prim? | ||||||
|  | 
 | ||||||
|  |             lock (m_parts) | ||||||
|  |             { | ||||||
|  |                 //update rootpart, if changed | ||||||
|  |                 if (m_rootPart.UUID != updatedSog.RootPart.UUID) | ||||||
|  |                 { | ||||||
|  |                     m_rootPart = updatedSog.RootPart; | ||||||
|  |                     rootPartChanged = true; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 //foreach (KeyValuePair<UUID, SceneObjectPart> pair in updatedSog.Parts) | ||||||
|  |                 foreach (SceneObjectPart updatedPart in updatedSog.Parts) | ||||||
|  |                 { | ||||||
|  |                     UUID partUUID = updatedPart.UUID; | ||||||
|  |                     Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Unchanged; | ||||||
|  |                     if (HasChildPrim(partUUID)) | ||||||
|  |                     { | ||||||
|  |                         //update the existing part | ||||||
|  |                         SceneObjectPart oldPart = GetChildPart(partUUID); | ||||||
|  |                         partUpdateResult = oldPart.UpdateAllProperties(updatedPart); | ||||||
|  |                         updatedParts.Add(partUUID, updatedPart); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         //a new part | ||||||
|  |                         //m_parts.Add(partUUID, updatedPart); | ||||||
|  |                         AddPart(updatedPart); | ||||||
|  |                         partUpdateResult = Scene.ObjectUpdateResult.New; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if (partUpdateResult != Scene.ObjectUpdateResult.Unchanged) | ||||||
|  |                     { | ||||||
|  |                         if (partUpdateResult == Scene.ObjectUpdateResult.New) | ||||||
|  |                             groupUpdateResult = Scene.ObjectUpdateResult.Updated; | ||||||
|  |                         else | ||||||
|  |                             groupUpdateResult = partUpdateResult; //Error or Updated | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 //For any parts that are not in the updatesParts (the old parts that are still in updatedSog), delete them. | ||||||
|  |                 foreach (SceneObjectPart oldPart in this.Parts) | ||||||
|  |                 { | ||||||
|  |                     if (!updatedParts.ContainsKey(oldPart.UUID)) | ||||||
|  |                     { | ||||||
|  |                         m_parts.Remove(oldPart.UUID); | ||||||
|  |                         partsRemoved = true; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 //Update the rootpart's ID in each non root parts | ||||||
|  |                 if (rootPartChanged) | ||||||
|  |                 { | ||||||
|  |                     UpdateParentIDs(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (partsRemoved) | ||||||
|  |             { | ||||||
|  |                 groupUpdateResult = Scene.ObjectUpdateResult.Updated; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |             //update the authoritative scene that this object is located, which is identified by (LocX, LocY) | ||||||
|  |             if (this.m_locX != updatedSog.LocX) | ||||||
|  |             { | ||||||
|  |                 this.m_locX = updatedSog.LocX; | ||||||
|  |                 groupUpdateResult = Scene.ObjectUpdateResult.Updated; | ||||||
|  |             } | ||||||
|  |             if (this.m_locY != updatedSog.LocY) | ||||||
|  |             { | ||||||
|  |                 this.m_locY = updatedSog.LocY; | ||||||
|  |                 groupUpdateResult = Scene.ObjectUpdateResult.Updated; | ||||||
|  |             } | ||||||
|  |              * */ | ||||||
|  | 
 | ||||||
|  |             //Schedule updates to be sent out, if the local copy has just been updated | ||||||
|  |             //(1) if we are debugging the actor with a viewer attaching to it, | ||||||
|  |             //we need to schedule updates to be sent to the viewer. | ||||||
|  |             //(2) or if we are a relaying node to relay updates, we need to forward the updates. | ||||||
|  |             //NOTE: LastUpdateTimeStamp and LastUpdateActorID should be kept the same as in the received copy of the object. | ||||||
|  |             if (groupUpdateResult == Scene.ObjectUpdateResult.Updated) | ||||||
|  |             { | ||||||
|  |                 ScheduleGroupForFullUpdate_SyncInfoUnchanged(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return groupUpdateResult; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void ScheduleGroupForFullUpdate_SyncInfoUnchanged() | ||||||
|  |         { | ||||||
|  |             if (IsAttachment) | ||||||
|  |                 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); | ||||||
|  | 
 | ||||||
|  |             checkAtTargets(); | ||||||
|  |             RootPart.ScheduleFullUpdate_SyncInfoUnchanged(); | ||||||
|  | 
 | ||||||
|  |             lock (m_parts) | ||||||
|  |             { | ||||||
|  |                 foreach (SceneObjectPart part in this.Parts) | ||||||
|  |                 { | ||||||
|  |                     if (part != RootPart) | ||||||
|  |                         part.ScheduleFullUpdate_SyncInfoUnchanged(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         #endregion |         #endregion | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3147,6 +3147,8 @@ namespace OpenSim.Region.Framework.Scenes | ||||||
| 
 | 
 | ||||||
|             //SYMMETRIC SYNC |             //SYMMETRIC SYNC | ||||||
| 
 | 
 | ||||||
|  |             m_parentGroup.Scene.RegionSyncModule.QueueSceneObjectPartForUpdate(this); | ||||||
|  |              | ||||||
|             //end of SYMMETRIC SYNC |             //end of SYMMETRIC SYNC | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -4962,6 +4964,158 @@ namespace OpenSim.Region.Framework.Scenes | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         //!!!!!! -- TODO:  | ||||||
|  |         //!!!!!! -- We should call UpdateXXX functions to update each property, cause some of such updates involves sanity checking. | ||||||
|  |         public Scene.ObjectUpdateResult UpdateAllProperties(SceneObjectPart updatedPart) | ||||||
|  |         { | ||||||
|  |             //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |             //NOTE!!!: So far this function is written with Script Engine updating local Scene cache in mind. | ||||||
|  |             //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  | 
 | ||||||
|  |             ////////////////////Assumptions: //////////////////// | ||||||
|  |             //(1) prim's UUID and LocalID shall not change (UUID is the unique identifies, LocalID is used to refer to the prim by, say scripts) | ||||||
|  |             //(2) RegionHandle won't be updated -- each copy of Scene is hosted on a region with different region handle | ||||||
|  |             //(3) ParentID won't be updated -- if the rootpart of the SceneObjectGroup changed, that will be updated in SceneObjectGroup.UpdateObjectProperties | ||||||
|  | 
 | ||||||
|  |             ////////////////////Furture enhancements://////////////////// | ||||||
|  |             //For now, we only update the set of properties that are included in serialization.  | ||||||
|  |             //See SceneObjectSerializer for the properties that are included in a serialized SceneObjectPart. | ||||||
|  |             //Later on, we may implement update functions that allow updating certain properties or certain buckets of properties. | ||||||
|  | 
 | ||||||
|  |             if (updatedPart == null) | ||||||
|  |                 return Scene.ObjectUpdateResult.Error; | ||||||
|  | 
 | ||||||
|  |             if (m_lastUpdateTimeStamp > updatedPart.LastUpdateTimeStamp) | ||||||
|  |             { | ||||||
|  |                 //Our timestamp is more update to date, keep our values of the properties. Do not update anything. | ||||||
|  |                 return Scene.ObjectUpdateResult.Unchanged; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (m_lastUpdateTimeStamp == updatedPart.LastUpdateTimeStamp) | ||||||
|  |             { | ||||||
|  |                 //if (m_parentGroup.Scene.GetActorID() != updatedPart.LastUpdatedByActorID) | ||||||
|  |                 if (m_lastUpdateByActorID != updatedPart.LastUpdateActorID) | ||||||
|  |                 { | ||||||
|  |                     m_log.Warn("Different actors modified SceneObjetPart " + UUID + " with the same TimeStamp, CONFLICT RESOLUTION TO BE IMPLEMENTED!!!!"); | ||||||
|  |                     return Scene.ObjectUpdateResult.Unchanged; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 //My own update was relayed back. Don't relay it. | ||||||
|  |                 return Scene.ObjectUpdateResult.Unchanged; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //Otherwise, our timestamp is less up to date, update the prim with the received copy | ||||||
|  | 
 | ||||||
|  |             Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Updated; | ||||||
|  | 
 | ||||||
|  |             //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; | ||||||
|  | 
 | ||||||
|  |             //Update the timestamp and LastUpdatedByActorID first. | ||||||
|  |             this.m_lastUpdateByActorID = updatedPart.LastUpdateActorID; | ||||||
|  |             this.m_lastUpdateTimeStamp = updatedPart.LastUpdateTimeStamp; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             /* | ||||||
|  |             this.m_inventory.Items = (TaskInventoryDictionary)updatedPart.m_inventory.Items.Clone(); | ||||||
|  |             //update shape information, for now, only update fileds in Shape whose set functions are defined in PrimitiveBaseShape | ||||||
|  |             this.Shape = updatedPart.Shape.Copy(); | ||||||
|  |             this.Shape.TextureEntry = updatedPart.Shape.TextureEntry; | ||||||
|  |              * */ | ||||||
|  | 
 | ||||||
|  |             return partUpdateResult; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 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(). | ||||||
|  |         /// </summary> | ||||||
|  |         public void ScheduleFullUpdate_SyncInfoUnchanged() | ||||||
|  |         { | ||||||
|  |             //            m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId); | ||||||
|  | 
 | ||||||
|  |             if (m_parentGroup != null) | ||||||
|  |             { | ||||||
|  |                 m_parentGroup.QueueForUpdateCheck(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             int timeNow = Util.UnixTimeSinceEpoch(); | ||||||
|  | 
 | ||||||
|  |             // If multiple updates are scheduled on the same second, we still need to perform all of them | ||||||
|  |             // So we'll force the issue by bumping up the timestamp so that later processing sees these need | ||||||
|  |             // to be performed. | ||||||
|  |             if (timeNow <= TimeStampFull) | ||||||
|  |             { | ||||||
|  |                 TimeStampFull += 1; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 TimeStampFull = (uint)timeNow; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             m_updateFlag = 2; | ||||||
|  | 
 | ||||||
|  |             //            m_log.DebugFormat( | ||||||
|  |             //                "[SCENE OBJECT PART]: Scheduling full  update for {0}, {1} at {2}", | ||||||
|  |             //                UUID, Name, TimeStampFull); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         #endregion  |         #endregion  | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Huaiyu (Kitty) Liu
						Huaiyu (Kitty) Liu