diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 2f67eec957..1bcc664136 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -289,7 +289,15 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule }); } - + public void SendTerrainUpdates(string lastUpdateActorID) + { + if(m_isSyncRelay || m_actorID.Equals(lastUpdateActorID)) + { + //m_scene.Heightmap should have been updated already by the caller, send it out + //SendSyncMessage(SymmetricSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()); + SendTerrainUpdateMessage(); + } + } #endregion //IRegionSyncModule @@ -713,6 +721,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + + /// /// The handler for processing incoming sync messages. /// @@ -723,13 +733,19 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { case SymmetricSyncMessage.MsgType.GetTerrain: { - SendSyncMessage(SymmetricSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()); + //SendSyncMessage(SymmetricSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()); + SendTerrainUpdateMessage(); return; } case SymmetricSyncMessage.MsgType.Terrain: { + /* m_scene.Heightmap.LoadFromXmlString(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)); + //Inform the terrain module that terrain has been updated + m_scene.RequestModuleInterface().TaintTerrain(); m_log.Debug(LogHeader+": Synchronized terrain"); + * */ + HandleTerrainUpdateMessage(msg); return; } case SymmetricSyncMessage.MsgType.GetObjects: @@ -764,7 +780,28 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } - public void HandleAddOrUpdateObjectBySynchronization(SymmetricSyncMessage msg) + private void HandleTerrainUpdateMessage(SymmetricSyncMessage msg) + { + // Get the data from message and error check + OSDMap data = DeserializeMessage(msg); + + if (data == null) + { + SymmetricSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data."); + return; + } + + string msgData = data["terrain"].AsString(); + long lastUpdateTimeStamp = data["actorID"].AsLong(); + string lastUpdateActorID = data["timeStamp"].AsString(); + + //set new terrain + m_scene.Heightmap.LoadFromXmlString(msgData); + m_scene.RequestModuleInterface().TaintTerrianBySynchronization(lastUpdateTimeStamp, lastUpdateActorID); ; + m_log.Debug(LogHeader + ": Synchronized terrain"); + } + + private void HandleAddOrUpdateObjectBySynchronization(SymmetricSyncMessage msg) { string sogxml = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); @@ -797,6 +834,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + private void SendTerrainUpdateMessage() + { + string msgData = m_scene.Heightmap.SaveToXmlString(); + long lastUpdateTimeStamp; + string lastUpdateActorID; + m_scene.RequestModuleInterface().GetSyncInfo(out lastUpdateTimeStamp, out lastUpdateActorID); + + OSDMap data = new OSDMap(3); + data["terrain"] = OSD.FromString(msgData); + data["actorID"] = OSD.FromString(lastUpdateActorID); + data["timeStamp"] = OSD.FromLong(lastUpdateTimeStamp); + + SendSyncMessage(SymmetricSyncMessage.MsgType.Terrain, OSDParser.SerializeJsonString(data)); + } + private void HandleRemovedObject(SymmetricSyncMessage msg) { // Get the data from message and error check diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs index c4a1d79c74..b4b960ace1 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs @@ -30,7 +30,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule NewObject, // objects UpdatedObject, // objects RemovedObject, // objects - // BIDIR //EchoRequest, //EchoResponse, diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 25d73c2c0f..276fcfe9a2 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -589,6 +589,56 @@ namespace OpenSim.Region.CoreModules.World.Terrain client.OnUnackedTerrain += client_OnUnackedTerrain; } + //SYMMETRIC SYNC + private long m_lastUpdateTimeStamp = DateTime.Now.Ticks; + public long LastUpdateTimeStamp + { + get { return m_lastUpdateTimeStamp; } + set { m_lastUpdateTimeStamp = value; } + } + + private string m_lastUpdateActorID; + public string LastUpdateActorID + { + get { return m_lastUpdateActorID; } + set { m_lastUpdateActorID = value; } + } + + private void SyncInfoUpdate(long timeStamp, string actorID) + { + m_lastUpdateTimeStamp = timeStamp; + m_lastUpdateActorID = actorID; + } + + /* + public void CheckForTerrainUpdatesBySynchronization(long timeStamp, string actorID) + { + SyncInfoUpdate(timeStamp, actorID); + CheckForTerrainUpdates(false); + } + * */ + + public void TaintTerrianBySynchronization(long timeStamp, string actorID) + { + SyncInfoUpdate(timeStamp, actorID); + CheckForTerrainUpdates(false, timeStamp, actorID); + } + + public bool TerrianModifiedLocally(string localActorID) + { + if (localActorID == m_lastUpdateActorID) + return true; + return false; + } + + public void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID) + { + lastUpdateTimeStamp = m_lastUpdateTimeStamp; + lastUpdateActorID = m_lastUpdateActorID; + } + + //end of SYMMETRIC SYNC + /// /// Checks to see if the terrain has been modified since last check /// but won't attempt to limit those changes to the limits specified in the estate settings @@ -596,7 +646,21 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// private void CheckForTerrainUpdates() { - CheckForTerrainUpdates(false); + //SYMMETRIC SYNC + + //Assumption: Thus function is only called when the terrain is updated by the local actor. + // Updating terrain during receiving sync messages from another actor will call CheckForTerrainUpdates. + + //Update the timestamp to the current time tick, and set the LastUpdateActorID to be self + long currentTimeTick = DateTime.Now.Ticks; + string localActorID = m_scene.GetSyncActorID(); + SyncInfoUpdate(currentTimeTick, localActorID); + //Check if the terrain has been modified and send out sync message if modified. + CheckForTerrainUpdates(false, currentTimeTick, localActorID); + + //end of SYMMETRIC SYNC + + //CheckForTerrainUpdates(false); } /// @@ -607,7 +671,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain /// currently invoked by client_OnModifyTerrain only and not the Commander interfaces /// should height map deltas be limited to the estate settings limits /// - private void CheckForTerrainUpdates(bool respectEstateSettings) + //private void CheckForTerrainUpdates(bool respectEstateSettings) + //SYMMETRIC SYNC: Change the interface, to input the right sync information for the most recent update + private void CheckForTerrainUpdates(bool respectEstateSettings, long lastUpdateTimeStamp, string lastUpdateActorID) + //end of SYMMETRIC SYNC { bool shouldTaint = false; float[] serialised = m_channel.GetFloatsSerialised(); @@ -636,6 +703,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain if (shouldTaint) { m_tainted = true; + //SYMMETRIC SYNC + //Terrain has been modified, send out sync message if needed + if (m_scene.RegionSyncModule != null) + { + m_scene.RegionSyncModule.SendTerrainUpdates(m_lastUpdateActorID); + } + //end of SYMMETRIC SYNC } } @@ -748,7 +822,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_painteffects[(StandardTerrainEffects) action].PaintEffect( m_channel, allowMask, west, south, height, size, seconds); - CheckForTerrainUpdates(!god); //revert changes outside estate limits + //CheckForTerrainUpdates(!god); //revert changes outside estate limits + //SYMMETRIC SYNC + CheckForTerrainUpdates(!god, DateTime.Now.Ticks, m_scene.GetSyncActorID()); + //end of SYMMETRIC SYNC } } else @@ -789,7 +866,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_floodeffects[(StandardTerrainEffects) action].FloodEffect( m_channel, fillArea, size); - CheckForTerrainUpdates(!god); //revert changes outside estate limits + //CheckForTerrainUpdates(!god); //revert changes outside estate limits + //SYMMETRIC SYNC + CheckForTerrainUpdates(!god, DateTime.Now.Ticks, m_scene.GetSyncActorID()); + //end of SYMMETRIC SYNC } } else diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs index 5947afb927..8f7606bbc7 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs @@ -64,5 +64,11 @@ namespace OpenSim.Region.Framework.Interfaces void InstallPlugin(string name, ITerrainEffect plug); void UndoTerrain(ITerrainChannel channel); + + //SYMMETRIC SYNC + void TaintTerrianBySynchronization(long timeStamp, string actorID); + bool TerrianModifiedLocally(string localActorID); + void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID); + //end of SYMMETRIC SYNC } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 36d99d78a7..8476ff6b82 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -612,6 +612,15 @@ namespace OpenSim.Region.Framework.Scenes Error //Errors happen during processing the message, e.g. the entity with the given UUID is not of type SceneObjectGroup } + public string GetSyncActorID() + { + if (m_DSGActorSyncModule != null) + { + return m_DSGActorSyncModule.ActorID; + } + return ""; + } + //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 diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 178f2b7e71..fd92853775 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4928,11 +4928,11 @@ namespace OpenSim.Region.Framework.Scenes //The ID the identifies which actor has caused the most recent update to the prim. //We use type "string" for the ID only to make it human-readable. - private string m_lastUpdateByActorID; + private string m_lastUpdateActorID; public string LastUpdateActorID { - get { return m_lastUpdateByActorID; } - set { m_lastUpdateByActorID = value; } + get { return m_lastUpdateActorID; } + set { m_lastUpdateActorID = value; } } public void UpdateTimestamp() @@ -4944,7 +4944,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentGroup != null) { - m_lastUpdateByActorID = m_parentGroup.Scene.ActorSyncModule.ActorID; + m_lastUpdateActorID = m_parentGroup.Scene.ActorSyncModule.ActorID; } else { @@ -4960,7 +4960,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentGroup != null) { UpdateTimestamp(); - m_lastUpdateByActorID = m_parentGroup.Scene.ActorSyncModule.ActorID; + m_lastUpdateActorID = m_parentGroup.Scene.ActorSyncModule.ActorID; } } @@ -4994,7 +4994,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_lastUpdateTimeStamp == updatedPart.LastUpdateTimeStamp) { //if (m_parentGroup.Scene.GetActorID() != updatedPart.LastUpdatedByActorID) - if (m_lastUpdateByActorID != updatedPart.LastUpdateActorID) + if (m_lastUpdateActorID != updatedPart.LastUpdateActorID) { m_log.Warn("Different actors modified SceneObjetPart " + UUID + " with the same TimeStamp, CONFLICT RESOLUTION TO BE IMPLEMENTED!!!!"); return Scene.ObjectUpdateResult.Unchanged; @@ -5067,7 +5067,7 @@ namespace OpenSim.Region.Framework.Scenes this.ParticleSystem = updatedPart.ParticleSystem; //Update the timestamp and LastUpdatedByActorID first. - this.m_lastUpdateByActorID = updatedPart.LastUpdateActorID; + this.m_lastUpdateActorID = updatedPart.LastUpdateActorID; this.m_lastUpdateTimeStamp = updatedPart.LastUpdateTimeStamp;