diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClient.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClient.cs index 21224dc034..871bc2caab 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClient.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClient.cs @@ -47,6 +47,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule Dictionary m_remoteAvatars = new Dictionary(); Dictionary m_localAvatars = new Dictionary(); + private bool m_symSync = false; + private Dictionary RemoteAvatars { get { return m_remoteAvatars; } @@ -276,6 +278,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule Send(new RegionSyncMessage(RegionSyncMessage.MsgType.AvatarAppearance, OSDParser.SerializeJsonString(data))); } + public void SetSymSync(bool symSync) + { + m_symSync = symSync; + } + // Handle an incoming message // TODO: This should not be synchronous with the receive! // Instead, handle messages from an incoming Queue so server doesn't block sending @@ -289,16 +296,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule RegionSyncMessage.HandleSuccess(LogHeader(), msg, String.Format("Syncing to region \"{0}\"", m_regionName)); return; } + //SYMMETRIC SYNC: do not handle terrian and object updates case RegionSyncMessage.MsgType.Terrain: { + if(!m_symSync) + { m_scene.Heightmap.LoadFromXmlString(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)); m_scene.PhysicsScene.SetTerrain(m_scene.Heightmap.GetFloatsSerialised()); RegionSyncMessage.HandleSuccess(LogHeader(), msg, "Synchronized terrain"); + } return; } case RegionSyncMessage.MsgType.NewObject: case RegionSyncMessage.MsgType.UpdatedObject: { + if(!m_symSync){ SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)); if (sog.IsDeleted) { @@ -306,23 +318,18 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } - /* - m_log.DebugFormat("{0} NewObject '{1}'", LogHeader(), sog.Name); - sog.ForEachPart(delegate(SceneObjectPart part) - { - m_log.DebugFormat("{0} Part {1}, lf={2} f={3}", LogHeader(), part.Name, - part.LocalFlags.ToString(), part.Flags.ToString()); - }); - */ if (m_scene.AddNewSceneObject(sog, true)); //RegionSyncMessage.HandleSuccess(LogHeader(), msg, String.Format("Object \"{0}\" ({1}) ({1}) updated.", sog.Name, sog.UUID.ToString(), sog.LocalId.ToString())); //else //RegionSyncMessage.HandleSuccess(LogHeader(), msg, String.Format("Object \"{0}\" ({1}) ({1}) added.", sog.Name, sog.UUID.ToString(), sog.LocalId.ToString())); sog.ScheduleGroupForFullUpdate(); + } return; } case RegionSyncMessage.MsgType.RemovedObject: { + if(!m_symSync) + { // Get the data from message and error check OSDMap data = DeserializeMessage(msg); if (data == null) @@ -346,8 +353,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // Delete the object from the scene m_scene.DeleteSceneObject(sog, false); RegionSyncMessage.HandleSuccess(LogHeader(), msg, String.Format("localID {0} deleted.", localID.ToString())); + } return; } + //end of SYMMETRIC SYNC case RegionSyncMessage.MsgType.NewAvatar: { // Get the data from message and error check @@ -823,8 +832,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule Send(new RegionSyncMessage(RegionSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName)); m_log.WarnFormat("Sending region name: \"{0}\"", m_scene.RegionInfo.RegionName); - Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetTerrain)); - Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetObjects)); + //SYMMETRIC SYNC: commenting out terrian and object updates + if (!m_symSync) + { + Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetTerrain)); + Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetObjects)); + } + //end of SYMMETRIC SYNC Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetAvatars)); // Register for events which will be forwarded to authoritative scene diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientModule.cs index 6afe2e65e2..a065be3002 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientModule.cs @@ -75,6 +75,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_serverport = syncConfig.GetInt(scene.RegionInfo.RegionName+"_ServerPort", serverPortDefault); m_scene.RegisterModuleInterface(this); + m_symsync = syncConfig.GetBoolean("SymSync", false); + // Setup the command line interface m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; InstallInterfaces(); @@ -156,6 +158,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private Object m_client_lock = new Object(); private RegionSyncClient m_client = null; + private bool m_symsync = false; #endregion @@ -239,6 +242,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Warn("[REGION SYNC CLIENT MODULE] Starting RegionSyncClient"); m_client = new RegionSyncClient(m_scene, m_serveraddr, m_serverport); + m_client.SetSymSync(m_symsync); m_client.Start(); } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientView.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientView.cs index 519115074a..a0dd8387a7 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientView.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncClientView.cs @@ -302,26 +302,34 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule RegionSyncMessage.HandleSuccess(LogHeader, msg, String.Format("Syncing to region \"{0}\"", m_regionName)); return; } + //SYMMETRIC SYNC: do not handle terrian and object updates case RegionSyncMessage.MsgType.GetTerrain: { - Send(new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString())); - RegionSyncMessage.HandleSuccess(LogHeader, msg, "Terrain sent"); + if (!m_scene.RegionSyncServerModule.IsSymSync) + { + Send(new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString())); + RegionSyncMessage.HandleSuccess(LogHeader, msg, "Terrain sent"); + } return; } case RegionSyncMessage.MsgType.GetObjects: { - EntityBase[] entities = m_scene.GetEntities(); - foreach(EntityBase e in entities) + if (!m_scene.RegionSyncServerModule.IsSymSync) { - if (e is SceneObjectGroup) + EntityBase[] entities = m_scene.GetEntities(); + foreach (EntityBase e in entities) { - string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)e); - Send(new RegionSyncMessage(RegionSyncMessage.MsgType.NewObject, sogxml)); + if (e is SceneObjectGroup) + { + string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)e); + Send(new RegionSyncMessage(RegionSyncMessage.MsgType.NewObject, sogxml)); + } } + RegionSyncMessage.HandleSuccess(LogHeader, msg, "Sent all scene objects"); } - RegionSyncMessage.HandleSuccess(LogHeader, msg, "Sent all scene objects"); return; } + //end of SYMMETRIC SYNC case RegionSyncMessage.MsgType.GetAvatars: { m_scene.ForEachScenePresence(delegate(ScenePresence presence) diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncServerModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncServerModule.cs index 7d36e24a94..787da59b3c 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncServerModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/RegionSyncServerModule.cs @@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { private static int DefaultPort = 13000; public static string ActorID = "XX"; + private static int PortUnknown = -1; + private static string IPAddrUnknown = ""; #region IRegionModule Members public void Initialise(Scene scene, IConfigSource config) @@ -100,18 +102,18 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //Get sync server info for Client Manager actors string serverAddr = scene.RegionInfo.RegionName + "_ServerIPAddress"; - m_serveraddr = syncConfig.GetString(serverAddr, "127.0.0.1"); + m_serveraddr = syncConfig.GetString(serverAddr, IPAddrUnknown); string serverPort = scene.RegionInfo.RegionName + "_ServerPort"; - m_serverport = syncConfig.GetInt(serverPort, DefaultPort); + m_serverport = syncConfig.GetInt(serverPort, PortUnknown); // Client manager load balancing m_maxClientsPerManager = syncConfig.GetInt("MaxClientsPerManager", 100); DefaultPort++; //Get sync server info for Script Engine actors string seServerAddr = scene.RegionInfo.RegionName + "_SceneToSESyncServerIP"; - m_seSyncServeraddr = syncConfig.GetString(seServerAddr, "127.0.0.1"); + m_seSyncServeraddr = syncConfig.GetString(seServerAddr, IPAddrUnknown); string seServerPort = scene.RegionInfo.RegionName + "_SceneToSESyncServerPort"; - m_seSyncServerport = syncConfig.GetInt(seServerPort, DefaultPort); + m_seSyncServerport = syncConfig.GetInt(seServerPort, PortUnknown); DefaultPort++; //Get sync server info for Physics Engine actors @@ -120,6 +122,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule string peServerPort = scene.RegionInfo.RegionName + "_SceneToPESyncServerPort"; m_peSyncServerport = syncConfig.GetInt(peServerPort, DefaultPort); DefaultPort++; + + m_symsync = syncConfig.GetBoolean("SymSync", false); //Get quark information QuarkInfo.SizeX = syncConfig.GetInt("QuarkSizeX", (int)Constants.RegionSize); @@ -149,28 +153,42 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); //m_scene.EventManager.OnNewPresence += new EventManager.OnNewPresenceDelegate(EventManager_OnNewPresence); m_scene.EventManager.OnRemovePresence += new EventManager.OnRemovePresenceDelegate(EventManager_OnRemovePresence); - m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(SceneGraph_OnObjectCreate); - m_scene.SceneGraph.OnObjectDuplicate += new ObjectDuplicateDelegate(SceneGraph_OnObjectDuplicate); - //m_scene.SceneGraph.OnObjectRemove += new ObjectDeleteDelegate(SceneGraph_OnObjectRemove); - //m_scene.StatsReporter.OnSendStatsResult += new SimStatsReporter.SendStatResult(StatsReporter_OnSendStatsResult); - m_scene.EventManager.OnOarFileLoaded += new EventManager.OarFileLoaded(EventManager_OnOarFileLoaded); - - m_log.Warn("[REGION SYNC SERVER MODULE] Starting RegionSyncServer"); + + //SYMMETRIC SYNC: do not handle object updates + if (!m_symsync) + { + m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(SceneGraph_OnObjectCreate); + m_scene.SceneGraph.OnObjectDuplicate += new ObjectDuplicateDelegate(SceneGraph_OnObjectDuplicate); + //m_scene.SceneGraph.OnObjectRemove += new ObjectDeleteDelegate(SceneGraph_OnObjectRemove); + //m_scene.StatsReporter.OnSendStatsResult += new SimStatsReporter.SendStatResult(StatsReporter_OnSendStatsResult); + m_scene.EventManager.OnOarFileLoaded += new EventManager.OarFileLoaded(EventManager_OnOarFileLoaded); + } + //end of SYMMETRIC SYNC // Start the server and listen for RegionSyncClients - m_server = new RegionSyncServer(m_scene, m_serveraddr, m_serverport, m_maxClientsPerManager); - m_server.Start(); - m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); - m_statsTimer.Start(); + if (!m_serveraddr.Equals(IPAddrUnknown) && m_serverport != PortUnknown) + { + m_log.Warn("[REGION SYNC SERVER MODULE] Starting RegionSyncServer"); + m_server = new RegionSyncServer(m_scene, m_serveraddr, m_serverport, m_maxClientsPerManager); + m_server.Start(); + m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); + m_statsTimer.Start(); + } - m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToScriptEngineSyncServer"); - //Start the sync server for script engines - m_sceneToSESyncServer = new SceneToScriptEngineSyncServer(m_scene, m_seSyncServeraddr, m_seSyncServerport); - m_sceneToSESyncServer.Start(); + if (!m_seSyncServeraddr.Equals(IPAddrUnknown) && m_seSyncServerport != PortUnknown) + { + m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToScriptEngineSyncServer"); + //Start the sync server for script engines + m_sceneToSESyncServer = new SceneToScriptEngineSyncServer(m_scene, m_seSyncServeraddr, m_seSyncServerport); + m_sceneToSESyncServer.Start(); + } - m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToPhysEngineSyncServer"); - //Start the sync server for physics engines - m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport); - m_sceneToPESyncServer.Start(); + if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown) + { + m_log.Warn("[REGION SYNC SERVER MODULE] Starting SceneToPhysEngineSyncServer"); + //Start the sync server for physics engines + m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport); + m_sceneToPESyncServer.Start(); + } //m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised"); } @@ -275,25 +293,23 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { // 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) + + //SYMMETRIC SYNC: do not handle object updates + if (!m_symsync) { - if (!sog.IsDeleted) + foreach (SceneObjectGroup sog in primUpdates) { - /* - string sogxml = SceneObjectSerializer.ToXml2Format(sog); - - m_log.Debug("[REGION SYNC SERVER MODULE]: to update object " + sog.UUID + ", localID: "+sog.LocalId - + ", with color " + sog.RootPart.Shape.Textures.DefaultTexture.RGBA.A - + "," + sog.RootPart.Shape.Textures.DefaultTexture.RGBA.B + "," + sog.RootPart.Shape.Textures.DefaultTexture.RGBA.G - + "," + sog.RootPart.Shape.Textures.DefaultTexture.RGBA.R); - - m_server.Broadcast(new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedObject, sogxml)); - * */ - //KittyL: modified to broadcast to different types of actors - m_server.BroadcastToCM(RegionSyncMessage.MsgType.UpdatedObject, sog); - m_sceneToSESyncServer.SendToSE(RegionSyncMessage.MsgType.UpdatedObject, sog); + if (!sog.IsDeleted) + { + //KittyL: modified to broadcast to different types of actors + if (m_server != null) + m_server.BroadcastToCM(RegionSyncMessage.MsgType.UpdatedObject, sog); + if (m_sceneToSESyncServer != null) + m_sceneToSESyncServer.SendToSE(RegionSyncMessage.MsgType.UpdatedObject, sog); + } } } + //end of SYMMETRIC SYNC foreach (ScenePresence presence in presenceUpdates) { try @@ -379,7 +395,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule data["localID"] = OSD.FromUInteger(localID); RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.RemovedObject, OSDParser.SerializeJsonString(data)); //m_server.BroadcastToCM(rsm); - m_server.Broadcast(rsm); + if(m_server!=null) + m_server.Broadcast(rsm); //KittyL: Second, tell script engine to remove the object, identified by UUID //UUID objID = m_scene.GetSceneObjectPart(localID).ParentGroup.UUID; @@ -394,7 +411,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check //if the object part is already removed is the scene (part==null) m_log.Debug("Inform script engine about the deleted object"); - m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup); + if(m_sceneToSESyncServer!=null) + m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup); } } @@ -419,9 +437,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule public void SendLoadWorldMap(ITerrainChannel heightMap) { RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()); - m_server.Broadcast(msg); + if(m_server!=null) + m_server.Broadcast(msg); //KittyL: added for SE - m_sceneToSESyncServer.SendToAllConnectedSE(msg); + if(m_sceneToSESyncServer!=null) + m_sceneToSESyncServer.SendToAllConnectedSE(msg); } #region cruft @@ -490,6 +510,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private int m_peSyncServerport; private SceneToPhysEngineSyncServer m_sceneToPESyncServer = null; + //a boolean variable to indicate in symmetric sync is configured + private bool m_symsync = false; + + public bool IsSymSync + { + get { return IsSymSync; } + } //quark related information //private int QuarkInfo.SizeX; //private int QuarkInfo.SizeY; diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index ea6aaf587a..70b2d69f46 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -366,6 +366,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // Synchronization related functions, NOT exposed through IRegionSyncModule interface ///////////////////////////////////////////////////////////////////////////////////////// + private static int PortUnknown = -1; + private static string IPAddrUnknown = ""; + private ILog m_log; //private bool m_active = true; @@ -482,8 +485,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private void StartLocalSyncListener() { RegionSyncListenerInfo localSyncListenerInfo = GetLocalSyncListenerInfo(); - m_localSyncListener = new RegionSyncListener(localSyncListenerInfo, this); - m_localSyncListener.Start(); + + if (localSyncListenerInfo!=null) + { + m_log.Warn(LogHeader + " Starting SyncListener"); + m_localSyncListener = new RegionSyncListener(localSyncListenerInfo, this); + m_localSyncListener.Start(); + } //STATS TIMER: TO BE IMPLEMENTED //m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); @@ -494,11 +502,18 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //For now, we use configuration to access the information. Might be replaced by some Grid Service later on. private RegionSyncListenerInfo GetLocalSyncListenerInfo() { - string addr = m_sysConfig.GetString("SyncListenerIPAddress", "127.0.0.1"); - int port = m_sysConfig.GetInt("SyncListenerPort", 13000); - RegionSyncListenerInfo info = new RegionSyncListenerInfo(addr, port); + string addr = m_sysConfig.GetString("SyncListenerIPAddress", IPAddrUnknown); + int port = m_sysConfig.GetInt("SyncListenerPort", PortUnknown); - return info; + m_log.Warn(LogHeader + ", listener addr: " + addr + ", port: " + port); + + if (!addr.Equals(IPAddrUnknown) && port != PortUnknown) + { + RegionSyncListenerInfo info = new RegionSyncListenerInfo(addr, port); + return info; + } + + return null; } //Get the information for remote [IP:Port] to connect to for synchronization purpose. @@ -510,13 +525,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { //For now, we assume there is only one remote listener to connect to. Later on, //we may need to modify the code to read in multiple listeners. - string addr = m_sysConfig.GetString("SyncListenerIPAddress", "127.0.0.1"); - int port = m_sysConfig.GetInt("SyncListenerPort", 13000); - RegionSyncListenerInfo info = new RegionSyncListenerInfo(addr, port); - - m_remoteSyncListeners = new HashSet(); - - m_remoteSyncListeners.Add(info); + string addr = m_sysConfig.GetString("SyncListenerIPAddress", IPAddrUnknown); + int port = m_sysConfig.GetInt("SyncListenerPort", PortUnknown); + if (!addr.Equals(IPAddrUnknown) && port != PortUnknown) + { + RegionSyncListenerInfo info = new RegionSyncListenerInfo(addr, port); + m_remoteSyncListeners = new HashSet(); + m_remoteSyncListeners.Add(info); + } } //Start SyncListener if a listener is supposed to run on this actor; Otherwise, initiate connections to remote listeners. diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSyncServerModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSyncServerModule.cs index 7d97fb2db2..36f80507b1 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionSyncServerModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionSyncServerModule.cs @@ -38,6 +38,9 @@ namespace OpenSim.Region.Framework.Interfaces bool Active { get; } bool Synced { get; } + + bool IsSymSync { get; } //If SymSync is set to true in the config file, then Symmetric Sync is running and object updates should be handled through RegionSyncModule + void QueuePartForUpdate(SceneObjectPart part); void QueuePresenceForTerseUpdate(ScenePresence presence); void SendUpdates();