Merge branch 'dev' into physics
commit
e68d9a25b1
|
@ -411,6 +411,12 @@ namespace OpenSim
|
|||
|
||||
scene.StartTimer();
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
//For INonSharedRegionModule, there is no more PostInitialise(). So we trigger OnPostSceneCreation event here
|
||||
//to let the Sync modules to do their work once all modules are loaded and scene has interfaces to all of them.
|
||||
scene.EventManager.TriggerOnPostSceneCreation(scene);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
return clientServer;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
ActorID = syncConfig.GetString("ActorID", "ZZ");
|
||||
|
||||
// If syncConfig does not indicate "server", do not start up server mode
|
||||
string mode = syncConfig.GetString("Mode", "server").ToLower();
|
||||
//string mode = syncConfig.GetString("Mode", "server").ToLower();
|
||||
string mode = syncConfig.GetString("Mode", "").ToLower();
|
||||
if(mode != "server")
|
||||
{
|
||||
scene.RegionSyncEnabled = false;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) Contributors: TO BE FILLED
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Mono.Addins;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||
{
|
||||
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
|
||||
public class ClientManagerSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||
{
|
||||
#region INonSharedRegionModule
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||
m_active = false;
|
||||
if (syncConfig == null)
|
||||
{
|
||||
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||
return;
|
||||
}
|
||||
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||
{
|
||||
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||
|
||||
//Read in configuration, if the local actor is configured to be a client manager, load this module.
|
||||
if (!actorType.Equals("client_manager"))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shut down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_actorID = syncConfig.GetString("ActorID", "");
|
||||
if (m_actorID.Equals(""))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = true;
|
||||
|
||||
m_log.Warn(LogHeader + " Initialised");
|
||||
|
||||
}
|
||||
|
||||
//Called after Initialise()
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
//connect with scene
|
||||
m_scene = scene;
|
||||
|
||||
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||
|
||||
// Setup the command line interface
|
||||
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||
//InstallInterfaces();
|
||||
|
||||
//Register for the OnPostSceneCreation event
|
||||
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||
|
||||
//Register for Scene/SceneGraph events
|
||||
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ClientManager_OnObjectCreate);
|
||||
m_scene.EventManager.OnSymmetricSyncStop += ClientManager_OnSymmetricSyncStop;
|
||||
}
|
||||
|
||||
//Called after AddRegion() has been called for all region modules of the scene.
|
||||
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_scene = null;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "ClientManagerSyncModule"; }
|
||||
}
|
||||
|
||||
#endregion //INonSharedRegionModule
|
||||
|
||||
|
||||
#region IDSGActorSyncModule members and functions
|
||||
|
||||
private DSGActorTypes m_actorType = DSGActorTypes.ClientManager;
|
||||
public DSGActorTypes ActorType
|
||||
{
|
||||
get { return m_actorType; }
|
||||
}
|
||||
|
||||
private string m_actorID;
|
||||
public string ActorID
|
||||
{
|
||||
get { return m_actorID; }
|
||||
}
|
||||
|
||||
#endregion //IDSGActorSyncModule
|
||||
|
||||
#region ClientManagerSyncModule memebers and functions
|
||||
private ILog m_log;
|
||||
private bool m_active = false;
|
||||
public bool Active
|
||||
{
|
||||
get { return m_active; }
|
||||
}
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
private string LogHeader = "[ClientManagerSyncModule]";
|
||||
|
||||
/// <summary>
|
||||
/// Script Engine's action upon an object is added to the local scene
|
||||
/// </summary>
|
||||
private void ClientManager_OnObjectCreate(EntityBase entity)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientManager_OnSymmetricSyncStop()
|
||||
{
|
||||
//remove all objects
|
||||
m_scene.DeleteAllSceneObjects();
|
||||
}
|
||||
|
||||
#endregion //ScriptEngineSyncModule
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) Contributors: TO BE FILLED
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Mono.Addins;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||
{
|
||||
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
|
||||
public class PhysicsEngineSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||
{
|
||||
#region INonSharedRegionModule
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||
m_active = false;
|
||||
if (syncConfig == null)
|
||||
{
|
||||
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||
return;
|
||||
}
|
||||
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||
{
|
||||
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||
|
||||
//Read in configuration, if the local actor is configured to be a client manager, load this module.
|
||||
if (!actorType.Equals("physics_engine"))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shut down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_actorID = syncConfig.GetString("ActorID", "");
|
||||
if (m_actorID.Equals(""))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = true;
|
||||
|
||||
m_log.Warn(LogHeader + " Initialised");
|
||||
|
||||
}
|
||||
|
||||
//Called after Initialise()
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
//connect with scene
|
||||
m_scene = scene;
|
||||
|
||||
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||
|
||||
// Setup the command line interface
|
||||
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||
//InstallInterfaces();
|
||||
|
||||
//Register for the OnPostSceneCreation event
|
||||
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||
|
||||
//Register for Scene/SceneGraph events
|
||||
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(PhysicsEngine_OnObjectCreate);
|
||||
m_scene.EventManager.OnSymmetricSyncStop += PhysicsEngine_OnSymmetricSyncStop;
|
||||
}
|
||||
|
||||
//Called after AddRegion() has been called for all region modules of the scene.
|
||||
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_scene = null;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "PhysicsEngineSyncModule"; }
|
||||
}
|
||||
|
||||
#endregion //INonSharedRegionModule
|
||||
|
||||
|
||||
#region IDSGActorSyncModule members and functions
|
||||
|
||||
private DSGActorTypes m_actorType = DSGActorTypes.PhysicsEngine;
|
||||
public DSGActorTypes ActorType
|
||||
{
|
||||
get { return m_actorType; }
|
||||
}
|
||||
|
||||
private string m_actorID;
|
||||
public string ActorID
|
||||
{
|
||||
get { return m_actorID; }
|
||||
}
|
||||
|
||||
#endregion //IDSGActorSyncModule
|
||||
|
||||
#region PhysicsEngineSyncModule memebers and functions
|
||||
private ILog m_log;
|
||||
private bool m_active = false;
|
||||
public bool Active
|
||||
{
|
||||
get { return m_active; }
|
||||
}
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
private string LogHeader = "[PhysicsEngineSyncModule]";
|
||||
|
||||
/// <summary>
|
||||
/// Script Engine's action upon an object is added to the local scene
|
||||
/// </summary>
|
||||
private void PhysicsEngine_OnObjectCreate(EntityBase entity)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void PhysicsEngine_OnSymmetricSyncStop()
|
||||
{
|
||||
//remove all objects
|
||||
m_scene.DeleteAllSceneObjects();
|
||||
}
|
||||
|
||||
#endregion //ScriptEngineSyncModule
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) Contributors: TO BE FILLED
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Mono.Addins;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
|
||||
public class ScenePersistenceSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||
{
|
||||
#region INonSharedRegionModule
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||
m_active = false;
|
||||
if (syncConfig == null)
|
||||
{
|
||||
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||
return;
|
||||
}
|
||||
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||
{
|
||||
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||
if (!actorType.Equals("scene_persistence"))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_actorID = syncConfig.GetString("ActorID", "");
|
||||
if (m_actorID.Equals(""))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = true;
|
||||
|
||||
m_log.Warn(LogHeader+" Initialised");
|
||||
|
||||
}
|
||||
|
||||
//Called after Initialise()
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
m_log.Warn(LogHeader + " AddRegion() called");
|
||||
//connect with scene
|
||||
m_scene = scene;
|
||||
|
||||
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||
|
||||
// Setup the command line interface
|
||||
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||
//InstallInterfaces();
|
||||
|
||||
//Register for the OnPostSceneCreation event
|
||||
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||
|
||||
//Register for Scene/SceneGraph events
|
||||
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate);
|
||||
}
|
||||
|
||||
//Called after AddRegion() has been called for all region modules of the scene.
|
||||
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||
// So to try to access other region modules in RegionLoaded, e.g. RegionSyncModule, is not a good idea.
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
m_log.Warn(LogHeader + " RegionLoaded() called");
|
||||
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_scene = null;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "ScenePersistenceSyncModule"; }
|
||||
}
|
||||
|
||||
#endregion //INonSharedRegionModule
|
||||
|
||||
#region IDSGActorSyncModule members and functions
|
||||
|
||||
private DSGActorTypes m_actorType = DSGActorTypes.ScenePersistence;
|
||||
public DSGActorTypes ActorType
|
||||
{
|
||||
get { return m_actorType; }
|
||||
}
|
||||
|
||||
private string m_actorID;
|
||||
public string ActorID
|
||||
{
|
||||
get { return m_actorID; }
|
||||
}
|
||||
|
||||
#endregion //IDSGActorSyncModule
|
||||
|
||||
#region ScenePersistenceSyncModule memebers and functions
|
||||
private ILog m_log;
|
||||
private bool m_active = false;
|
||||
public bool Active
|
||||
{
|
||||
get { return m_active; }
|
||||
}
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
private string LogHeader = "[ScenePersistenceSyncModule]";
|
||||
|
||||
public void OnPostSceneCreation(Scene createdScene)
|
||||
{
|
||||
//If this is the local scene the actor is working on, do something
|
||||
if (createdScene == m_scene)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ScenePersistence's actions upon an object is added to the local scene.
|
||||
/// </summary>
|
||||
private void ScenePersistence_OnObjectCreate(EntityBase entity)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
m_log.Warn(LogHeader + ": link to backup for " + entity.UUID);
|
||||
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
||||
sog.AttachToBackup();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion //ScenePersistenceSyncModule
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) Contributors: TO BE FILLED
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Client;
|
||||
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Mono.Addins;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||
{
|
||||
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")]
|
||||
public class ScriptEngineSyncModule : INonSharedRegionModule, IDSGActorSyncModule
|
||||
{
|
||||
#region INonSharedRegionModule
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
IConfig syncConfig = config.Configs["RegionSyncModule"];
|
||||
m_active = false;
|
||||
if (syncConfig == null)
|
||||
{
|
||||
m_log.Warn(LogHeader + " No RegionSyncModule config section found. Shutting down.");
|
||||
return;
|
||||
}
|
||||
else if (!syncConfig.GetBoolean("Enabled", false))
|
||||
{
|
||||
m_log.Warn(LogHeader + " RegionSyncModule is not enabled. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
string actorType = syncConfig.GetString("DSGActorType", "").ToLower();
|
||||
if (!actorType.Equals("script_engine"))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": not configured as Scene Persistence Actor. Shut down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_actorID = syncConfig.GetString("ActorID", "");
|
||||
if (m_actorID.Equals(""))
|
||||
{
|
||||
m_log.Warn(LogHeader + ": ActorID not specified in config file. Shutting down.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = true;
|
||||
|
||||
m_log.Warn(LogHeader + " Initialised");
|
||||
|
||||
}
|
||||
|
||||
//Called after Initialise()
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
m_log.Warn(LogHeader + " AddRegion() called");
|
||||
//connect with scene
|
||||
m_scene = scene;
|
||||
|
||||
//register the module with SceneGraph. If needed, SceneGraph checks the module's ActorType to know what type of module it is.
|
||||
m_scene.RegisterModuleInterface<IDSGActorSyncModule>(this);
|
||||
|
||||
// Setup the command line interface
|
||||
//m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
|
||||
//InstallInterfaces();
|
||||
|
||||
//Register for the OnPostSceneCreation event
|
||||
//m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
|
||||
|
||||
//Register for Scene/SceneGraph events
|
||||
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScriptEngine_OnObjectCreate);
|
||||
m_scene.EventManager.OnSymmetricSyncStop += ScriptEngine_OnSymmetricSyncStop;
|
||||
}
|
||||
|
||||
//Called after AddRegion() has been called for all region modules of the scene.
|
||||
//NOTE::However, at this point, Scene may not have requested all the needed region module interfaces yet.
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
m_scene = null;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "ScriptEngineSyncModule"; }
|
||||
}
|
||||
|
||||
#endregion //INonSharedRegionModule
|
||||
|
||||
#region IDSGActorSyncModule members and functions
|
||||
|
||||
private DSGActorTypes m_actorType = DSGActorTypes.ScriptEngine;
|
||||
public DSGActorTypes ActorType
|
||||
{
|
||||
get { return m_actorType; }
|
||||
}
|
||||
|
||||
private string m_actorID;
|
||||
public string ActorID
|
||||
{
|
||||
get { return m_actorID; }
|
||||
}
|
||||
|
||||
#endregion //IDSGActorSyncModule
|
||||
|
||||
|
||||
#region ScriptEngineSyncModule memebers and functions
|
||||
private ILog m_log;
|
||||
private bool m_active = false;
|
||||
public bool Active
|
||||
{
|
||||
get { return m_active; }
|
||||
}
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
private string LogHeader = "[ScriptEngineSyncModule]";
|
||||
|
||||
public void OnPostSceneCreation(Scene createdScene)
|
||||
{
|
||||
//If this is the local scene the actor is working on, do something
|
||||
if (createdScene == m_scene)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Script Engine's action upon an object is added to the local scene
|
||||
/// </summary>
|
||||
private void ScriptEngine_OnObjectCreate(EntityBase entity)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
m_log.Warn(LogHeader + ": start script for obj " + entity.UUID);
|
||||
SceneObjectGroup sog = (SceneObjectGroup)entity;
|
||||
sog.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
|
||||
sog.ResumeScripts();
|
||||
}
|
||||
}
|
||||
|
||||
public void ScriptEngine_OnSymmetricSyncStop()
|
||||
{
|
||||
//Inform script engine to save script states and stop scripts
|
||||
m_scene.EventManager.TriggerScriptEngineSyncStop();
|
||||
//remove all objects
|
||||
m_scene.DeleteAllSceneObjects();
|
||||
}
|
||||
|
||||
#endregion //ScriptEngineSyncModule
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) Contributors: TO BE FILLED
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||
{
|
||||
//Initial code in SymmetricSyncMessage copied from RegionSyncMessage.
|
||||
|
||||
/// <summary>
|
||||
/// Types of symmetric sync messages among actors.
|
||||
/// NOTE:: To enable message subscription, we may need to move the definition of MsgType to, say IRegionSyncModule, so that it can be exposed to other region modules.
|
||||
/// </summary>
|
||||
public class SymmetricSyncMessage
|
||||
{
|
||||
#region MsgType Enum
|
||||
public enum MsgType
|
||||
{
|
||||
Null,
|
||||
// Actor -> SIM(Scene)
|
||||
GetTerrain,
|
||||
GetObjects,
|
||||
|
||||
// SIM -> CM
|
||||
Terrain,
|
||||
NewObject, // objects
|
||||
UpdatedObject, // objects
|
||||
RemovedObject, // objects
|
||||
// BIDIR
|
||||
//EchoRequest,
|
||||
//EchoResponse,
|
||||
RegionName,
|
||||
//RegionStatus,
|
||||
ActorID,
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Member Data
|
||||
private MsgType m_type;
|
||||
private byte[] m_data;
|
||||
static ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public SymmetricSyncMessage(MsgType type, byte[] data)
|
||||
{
|
||||
m_type = type;
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
public SymmetricSyncMessage(MsgType type, string msg)
|
||||
{
|
||||
m_type = type;
|
||||
m_data = System.Text.Encoding.ASCII.GetBytes(msg);
|
||||
}
|
||||
|
||||
public SymmetricSyncMessage(MsgType type)
|
||||
{
|
||||
m_type = type;
|
||||
m_data = new byte[0];
|
||||
}
|
||||
|
||||
public SymmetricSyncMessage(Stream stream)
|
||||
{
|
||||
//ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
//try
|
||||
{
|
||||
m_type = (MsgType)Utils.BytesToInt(GetBytesFromStream(stream, 4));
|
||||
int length = Utils.BytesToInt(GetBytesFromStream(stream, 4));
|
||||
m_data = GetBytesFromStream(stream, length);
|
||||
//log.WarnFormat("RegionSyncMessage Constructed {0} ({1} bytes)", m_type.ToString(), length);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] GetBytesFromStream(Stream stream, int count)
|
||||
{
|
||||
// Loop to receive the message length
|
||||
byte[] ret = new byte[count];
|
||||
int i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
i += stream.Read(ret, i, count - i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
public MsgType Type
|
||||
{
|
||||
get { return m_type; }
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get { return m_data.Length; }
|
||||
}
|
||||
|
||||
public byte[] Data
|
||||
{
|
||||
get { return m_data; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversions
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
byte[] buf = new byte[m_data.Length + 8];
|
||||
Utils.IntToBytes((int)m_type, buf, 0);
|
||||
Utils.IntToBytes(m_data.Length, buf, 4);
|
||||
Array.Copy(m_data, 0, buf, 8, m_data.Length);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0} ({1} bytes)", m_type.ToString(), m_data.Length.ToString());
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public static void HandleSuccess(string header, SymmetricSyncMessage msg, string message)
|
||||
{
|
||||
m_log.WarnFormat("{0} Handled {1}: {2}", header, msg.ToString(), message);
|
||||
}
|
||||
|
||||
public static void HandleTrivial(string header, SymmetricSyncMessage msg, string message)
|
||||
{
|
||||
m_log.WarnFormat("{0} Issue handling {1}: {2}", header, msg.ToString(), message);
|
||||
}
|
||||
|
||||
public static void HandleWarning(string header, SymmetricSyncMessage msg, string message)
|
||||
{
|
||||
m_log.WarnFormat("{0} Warning handling {1}: {2}", header, msg.ToString(), message);
|
||||
}
|
||||
|
||||
public static void HandleError(string header, SymmetricSyncMessage msg, string message)
|
||||
{
|
||||
m_log.WarnFormat("{0} Error handling {1}: {2}", header, msg.ToString(), message);
|
||||
}
|
||||
|
||||
public static bool HandlerDebug(string header, SymmetricSyncMessage msg, string message)
|
||||
{
|
||||
m_log.WarnFormat("{0} DBG ({1}): {2}", header, msg.ToString(), message);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* Copyright (c) Contributors: TO BE FILLED
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
||||
{
|
||||
// For implementations, a lot was copied from RegionSyncClientView, especially the SendLoop/ReceiveLoop.
|
||||
public class SyncConnector
|
||||
{
|
||||
private TcpClient m_tcpConnection = null;
|
||||
private RegionSyncListenerInfo m_remoteListenerInfo = null;
|
||||
private Thread m_rcvLoop;
|
||||
private Thread m_send_loop;
|
||||
|
||||
private string LogHeader = "[SYNC CONNECTOR]";
|
||||
// The logfile
|
||||
private ILog m_log;
|
||||
|
||||
//members for in/out messages queueing
|
||||
object stats = new object();
|
||||
private long queuedUpdates=0;
|
||||
private long dequeuedUpdates=0;
|
||||
private long msgsIn=0;
|
||||
private long msgsOut=0;
|
||||
private long bytesIn=0;
|
||||
private long bytesOut=0;
|
||||
private int msgCount = 0;
|
||||
// A queue for outgoing traffic.
|
||||
private BlockingUpdateQueue m_outQ = new BlockingUpdateQueue();
|
||||
|
||||
private RegionSyncModule m_regionSyncModule = null;
|
||||
|
||||
private int m_connectorNum;
|
||||
public int 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
|
||||
private string m_syncOtherSideRegionName="";
|
||||
public string OtherSideRegionName
|
||||
{
|
||||
get { return m_syncOtherSideRegionName; }
|
||||
}
|
||||
|
||||
// Check if the client is connected
|
||||
public bool Connected
|
||||
{ get { return (m_tcpConnection !=null && m_tcpConnection.Connected); } }
|
||||
|
||||
public string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_syncOtherSideRegionName == null)
|
||||
return String.Format("SyncConnector #{0}", m_connectorNum);
|
||||
return String.Format("SyncConnector #{0} ({1:10})", m_connectorNum, m_syncOtherSideRegionName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor that will be called when a SyncConnector is created passively: a remote SyncConnector has initiated the connection.
|
||||
/// </summary>
|
||||
/// <param name="connectorNum"></param>
|
||||
/// <param name="tcpclient"></param>
|
||||
public SyncConnector(int connectorNum, TcpClient tcpclient, RegionSyncModule syncModule)
|
||||
{
|
||||
m_tcpConnection = tcpclient;
|
||||
m_connectorNum = connectorNum;
|
||||
m_regionSyncModule = syncModule;
|
||||
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor that will be called when a SyncConnector is created actively: it is created to send connection request to a remote listener
|
||||
/// </summary>
|
||||
/// <param name="connectorNum"></param>
|
||||
/// <param name="listenerInfo"></param>
|
||||
public SyncConnector(int connectorNum, RegionSyncListenerInfo listenerInfo, RegionSyncModule syncModule)
|
||||
{
|
||||
m_remoteListenerInfo = listenerInfo;
|
||||
m_connectorNum = connectorNum;
|
||||
m_regionSyncModule = syncModule;
|
||||
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
}
|
||||
|
||||
//Connect to the remote listener
|
||||
public bool Connect()
|
||||
{
|
||||
m_tcpConnection = new TcpClient();
|
||||
try
|
||||
{
|
||||
m_tcpConnection.Connect(m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncServer at {1}:{2}", LogHeader, m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
|
||||
m_log.Warn(e.Message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start both the send and receive threads
|
||||
/// </summary>
|
||||
public void StartCommThreads()
|
||||
{
|
||||
// Create a thread for the receive loop
|
||||
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
|
||||
m_rcvLoop.Name = Description + " (ReceiveLoop)";
|
||||
m_log.WarnFormat("{0} Starting {1} thread", Description, m_rcvLoop.Name);
|
||||
m_rcvLoop.Start();
|
||||
|
||||
// Create a thread for the send loop
|
||||
m_send_loop = new Thread(new ThreadStart(delegate() { SendLoop(); }));
|
||||
m_send_loop.Name = Description + " (SendLoop)";
|
||||
m_log.WarnFormat("{0} Starting {1} thread", Description, m_send_loop.Name);
|
||||
m_send_loop.Start();
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
m_log.Warn(LogHeader + " shutdown connection");
|
||||
// Abort receive and send loop
|
||||
m_rcvLoop.Abort();
|
||||
m_send_loop.Abort();
|
||||
|
||||
// Close the connection
|
||||
m_tcpConnection.Client.Close();
|
||||
m_tcpConnection.Close();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Sending messages out to the other side of the connection
|
||||
///////////////////////////////////////////////////////////
|
||||
// Send messages from the update Q as fast as we can DeQueue them
|
||||
// *** This is the main send loop thread for each connected client
|
||||
private void SendLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Dequeue is thread safe
|
||||
byte[] update = m_outQ.Dequeue();
|
||||
lock (stats)
|
||||
dequeuedUpdates++;
|
||||
Send(update);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("{0} has disconnected: {1} (SendLoop)", Description, e.Message);
|
||||
}
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue update of an object/avatar into the outgoing queue, and return right away
|
||||
/// </summary>
|
||||
/// <param name="id">UUID of the object/avatar</param>
|
||||
/// <param name="update">the update infomation in byte format</param>
|
||||
public void EnqueueOutgoingUpdate(UUID id, byte[] update)
|
||||
{
|
||||
lock (stats)
|
||||
queuedUpdates++;
|
||||
// Enqueue is thread safe
|
||||
m_outQ.Enqueue(id, update);
|
||||
}
|
||||
|
||||
//Send out a messge directly. This should only by called for short messages that are not sent frequently.
|
||||
//Don't call this function for sending out updates. Call EnqueueOutgoingUpdate instead
|
||||
public void Send(SymmetricSyncMessage msg)
|
||||
{
|
||||
Send(msg.ToBytes());
|
||||
}
|
||||
|
||||
private void Send(byte[] data)
|
||||
{
|
||||
if (m_tcpConnection.Connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (stats)
|
||||
{
|
||||
msgsOut++;
|
||||
bytesOut += data.Length;
|
||||
}
|
||||
m_tcpConnection.GetStream().BeginWrite(data, 0, data.Length, ar =>
|
||||
{
|
||||
if (m_tcpConnection.Connected)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_tcpConnection.GetStream().EndWrite(ar);
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
m_log.WarnFormat("{0}:{1} has disconnected.", Description, m_connectorNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Receiving messages from the other side ofthe connection
|
||||
///////////////////////////////////////////////////////////
|
||||
private void ReceiveLoop()
|
||||
{
|
||||
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
|
||||
while (true && m_tcpConnection.Connected)
|
||||
{
|
||||
SymmetricSyncMessage msg;
|
||||
// Try to get the message from the network stream
|
||||
try
|
||||
{
|
||||
msg = new SymmetricSyncMessage(m_tcpConnection.GetStream());
|
||||
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
|
||||
}
|
||||
// If there is a problem reading from the client, shut 'er down.
|
||||
catch
|
||||
{
|
||||
//ShutdownClient();
|
||||
m_log.WarnFormat("{0}:{1} has disconnected.", Description, m_connectorNum);
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
// Try handling the message
|
||||
try
|
||||
{
|
||||
HandleMessage(msg);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", Description, e.Message, msg.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleMessage(SymmetricSyncMessage msg)
|
||||
{
|
||||
|
||||
msgCount++;
|
||||
switch (msg.Type)
|
||||
{
|
||||
case SymmetricSyncMessage.MsgType.RegionName:
|
||||
{
|
||||
m_syncOtherSideRegionName = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
|
||||
if (m_regionSyncModule.IsSyncRelay)
|
||||
{
|
||||
SymmetricSyncMessage outMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RegionName, m_regionSyncModule.LocalScene.RegionInfo.RegionName);
|
||||
Send(outMsg);
|
||||
}
|
||||
m_log.DebugFormat("Syncing to region \"{0}\"", m_syncOtherSideRegionName);
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
||||
//For any other messages, we simply deliver the message to RegionSyncModule for now.
|
||||
//Later on, we may deliver messages to different modules, say sync message to RegionSyncModule and event message to ActorSyncModule.
|
||||
m_regionSyncModule.HandleIncomingMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -205,6 +205,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
|||
|
||||
public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
|
||||
{
|
||||
return false;
|
||||
if (destination == null)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
|||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -607,7 +671,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
|||
/// currently invoked by client_OnModifyTerrain only and not the Commander interfaces
|
||||
/// <param name="respectEstateSettings">should height map deltas be limited to the estate settings limits</param>
|
||||
/// </summary>
|
||||
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
|
||||
|
|
|
@ -64,5 +64,21 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
void InstallPlugin(string name, ITerrainEffect plug);
|
||||
|
||||
void UndoTerrain(ITerrainChannel channel);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
void TaintTerrianBySynchronization(long timeStamp, string actorID);
|
||||
/// <summary>
|
||||
/// Return true if the most recent update on terrain is done locally (i.e. not by receiving a terrain-sync message).
|
||||
/// </summary>
|
||||
/// <param name="localActorID"></param>
|
||||
/// <returns></returns>
|
||||
bool TerrianModifiedLocally(string localActorID);
|
||||
/// <summary>
|
||||
/// Obtain the timestemp and actorID information for the most recent update on terrain.
|
||||
/// </summary>
|
||||
/// <param name="lastUpdateTimeStamp"></param>
|
||||
/// <param name="lastUpdateActorID"></param>
|
||||
void GetSyncInfo(out long lastUpdateTimeStamp, out string lastUpdateActorID);
|
||||
//end of SYMMETRIC SYNC
|
||||
}
|
||||
}
|
||||
|
|
|
@ -376,7 +376,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public delegate void RegionUp(GridRegion region);
|
||||
public event RegionUp OnRegionUp;
|
||||
|
||||
|
||||
public class MoneyTransferArgs : EventArgs
|
||||
{
|
||||
public UUID sender;
|
||||
|
@ -2184,7 +2183,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[EVENT MANAGER]: Delegate for TriggerOnSceneObjectLoaded failed - continuing. {0} {1}",
|
||||
"[EVENT MANAGER]: Delegate for TriggerScriptEngineSyncStop failed - continuing. {0} {1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
@ -2243,5 +2242,55 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
public event PostSceneCreation OnPostSceneCreation;
|
||||
public delegate void PostSceneCreation(Scene createdScene);
|
||||
|
||||
public void TriggerOnPostSceneCreation(Scene createdScene)
|
||||
{
|
||||
PostSceneCreation handler = OnPostSceneCreation;
|
||||
if (handler != null)
|
||||
{
|
||||
foreach (PostSceneCreation d in handler.GetInvocationList())
|
||||
{
|
||||
try
|
||||
{
|
||||
d(createdScene);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[EVENT MANAGER]: Delegate for TriggerOnPostSceneCreation failed - continuing. {0} {1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void SymmetricSyncStop();
|
||||
public event SymmetricSyncStop OnSymmetricSyncStop;
|
||||
public void TriggerOnSymmetricSyncStop()
|
||||
{
|
||||
SymmetricSyncStop handlerSymmetricSyncStop = OnSymmetricSyncStop;
|
||||
if (handlerSymmetricSyncStop != null)
|
||||
{
|
||||
foreach (SymmetricSyncStop d in handlerSymmetricSyncStop.GetInvocationList())
|
||||
{
|
||||
try
|
||||
{
|
||||
d();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[EVENT MANAGER]: Delegate for TriggerOnSymmetricSyncStop failed - continuing. {0} {1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//end of SYMMETRIC SYNC
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
get { return m_AvatarFactory; }
|
||||
}
|
||||
#region REGION SYNC
|
||||
|
||||
|
||||
#region REGION SYNC -- Asymmetric sync, old style, depreciated ---------
|
||||
|
||||
protected IRegionSyncServerModule m_regionSyncServerModule;
|
||||
protected IRegionSyncClientModule m_regionSyncClientModule;
|
||||
|
||||
|
@ -614,6 +617,100 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region SYMMETRIC SYNC
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//KittyL: 12/23/2010. SYMMETRIC SYNC: Implementation for the symmetric synchronization model.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private IRegionSyncModule m_regionSyncModule = null;
|
||||
public IRegionSyncModule RegionSyncModule
|
||||
{
|
||||
get { return m_regionSyncModule; }
|
||||
//set { m_regionSyncModule = value; }
|
||||
}
|
||||
|
||||
private IDSGActorSyncModule m_DSGActorSyncModule = null;
|
||||
public IDSGActorSyncModule ActorSyncModule
|
||||
{
|
||||
get { return m_DSGActorSyncModule; }
|
||||
|
||||
}
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
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
|
||||
public ObjectUpdateResult AddOrUpdateObjectBySynchronization(SceneObjectGroup sog)
|
||||
{
|
||||
return m_sceneGraph.AddOrUpdateObjectBySynchronization(sog);
|
||||
}
|
||||
|
||||
//Similar to DeleteSceneObject, except that this does not change LastUpdateActorID and LastUpdateTimeStamp
|
||||
public void DeleteSceneObjectBySynchronization(SceneObjectGroup group)
|
||||
{
|
||||
// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
|
||||
|
||||
//SceneObjectPart rootPart = group.GetChildPart(group.UUID);
|
||||
|
||||
// Serialise calls to RemoveScriptInstances to avoid
|
||||
// deadlocking on m_parts inside SceneObjectGroup
|
||||
lock (m_deleting_scene_object)
|
||||
{
|
||||
group.RemoveScriptInstances(true);
|
||||
}
|
||||
|
||||
SceneObjectPart[] partList = group.Parts;
|
||||
|
||||
foreach (SceneObjectPart part in partList)
|
||||
{
|
||||
if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
|
||||
{
|
||||
PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
|
||||
}
|
||||
else if (part.PhysActor != null)
|
||||
{
|
||||
PhysicsScene.RemovePrim(part.PhysActor);
|
||||
part.PhysActor = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (UnlinkSceneObject(group, false))
|
||||
{
|
||||
EventManager.TriggerObjectBeingRemovedFromScene(group);
|
||||
EventManager.TriggerParcelPrimCountTainted();
|
||||
}
|
||||
|
||||
bool silent = false; //do not suppress broadcasting changes to other clients, for debugging with viewers
|
||||
group.DeleteGroupFromScene(silent);
|
||||
|
||||
}
|
||||
|
||||
#endregion //SYMMETRIC SYNC
|
||||
|
||||
public ICapabilitiesModule CapsModule
|
||||
{
|
||||
get { return m_capsModule; }
|
||||
|
@ -1305,6 +1402,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
PhysEngineToSceneConnectorModule = RequestModuleInterface<IPhysEngineToSceneConnectorModule>();
|
||||
SceneToPhysEngineSyncServer = RequestModuleInterface<ISceneToPhysEngineServer>();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//SYMMETRIC SYNC (KittyL: started 12/23/2010)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
m_regionSyncModule = RequestModuleInterface<IRegionSyncModule>();
|
||||
m_DSGActorSyncModule = RequestModuleInterface<IDSGActorSyncModule>();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//end of SYMMETRIC SYNC
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Shoving this in here for now, because we have the needed
|
||||
// interfaces at this point
|
||||
//
|
||||
|
@ -1456,7 +1563,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// If it's a client manager, just send prim updates
|
||||
// This will get fixed later to only send to locally logged in presences rather than all presences
|
||||
// but requires pulling apart the concept of a client from the concept of a presence/avatar
|
||||
if (IsSyncedClient() || !RegionSyncEnabled)
|
||||
if (IsSyncedClient())
|
||||
|
||||
{
|
||||
ForEachScenePresence(delegate(ScenePresence sp) { sp.SendPrimUpdates(); });
|
||||
|
@ -1490,24 +1597,14 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_regionSyncServerModule.SendUpdates();
|
||||
}
|
||||
|
||||
/*
|
||||
// The authoritative sim should not try to send coarse locations
|
||||
// Leave this up to the client managers
|
||||
if (!IsSyncedServer())
|
||||
//SYMMETRIC SYNC
|
||||
|
||||
//NOTE: If it is configured as symmetric sync in opensim.ini, the above IsSyncedServer() or IsSyncedClient() should all return false
|
||||
if (RegionSyncModule != null)
|
||||
{
|
||||
if (m_frame % m_update_coarse_locations == 0)
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
RegionSyncModule.SendSceneUpdates();
|
||||
}
|
||||
* */
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
int tmpPhysicsMS2 = Util.EnvironmentTickCount();
|
||||
// Do not simulate physics locally if this is a synced client
|
||||
|
@ -2357,6 +2454,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
group.DeleteGroupFromScene(silent);
|
||||
|
||||
// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
//Set the ActorID and TimeStamp info for this latest update
|
||||
foreach (SceneObjectPart part in group.Parts)
|
||||
{
|
||||
part.SyncInfoUpdate();
|
||||
}
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -373,23 +373,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
sceneObject.AttachToScene(m_parentScene);
|
||||
|
||||
//KittyL: edited to support script engine actor
|
||||
//if (sendClientUpdates)
|
||||
// sceneObject.ScheduleGroupForFullUpdate();
|
||||
if (sendClientUpdates)
|
||||
{
|
||||
sceneObject.ScheduleGroupForFullUpdate();
|
||||
}
|
||||
|
||||
Entities.Add(sceneObject);
|
||||
|
||||
//KittyL: edited to support script engine actor
|
||||
//if (attachToBackup)
|
||||
// sceneObject.AttachToBackup();
|
||||
if (attachToBackup && m_parentScene.IsAuthoritativeScene())
|
||||
{
|
||||
if (attachToBackup)
|
||||
sceneObject.AttachToBackup();
|
||||
}
|
||||
|
||||
if (OnObjectCreate != null)
|
||||
OnObjectCreate(sceneObject);
|
||||
|
@ -465,7 +455,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
protected internal void AddToUpdateList(SceneObjectGroup obj)
|
||||
{
|
||||
lock (m_updateList)
|
||||
{
|
||||
m_updateList[obj.UUID] = obj;
|
||||
m_log.Debug("added " + obj.UUID + " to m_updateList");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -484,6 +477,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
lock (m_updateList)
|
||||
{
|
||||
updates = new List<SceneObjectGroup>(m_updateList.Values);
|
||||
|
||||
if (updates.Count > 0)
|
||||
{
|
||||
m_log.Debug("SceneGraph: " + updates.Count + " objects to send updates for");
|
||||
}
|
||||
|
||||
|
||||
m_updateList.Clear();
|
||||
}
|
||||
|
||||
|
@ -1928,7 +1928,103 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
}
|
||||
|
||||
#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
|
||||
{
|
||||
m_log.Debug("AddSceneObjectByStateSynch to be called");
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3456,5 +3456,144 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
this.m_locY = updatedSog.LocY;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2892,6 +2892,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// m_log.DebugFormat(
|
||||
// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
|
||||
// UUID, Name, TimeStampFull);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
|
||||
//update information (timestamp, actorID, etc) needed for synchronization across copies of Scene
|
||||
SyncInfoUpdate();
|
||||
|
||||
//end of SYMMETRIC SYNC
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2913,6 +2920,13 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// m_log.DebugFormat(
|
||||
// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
|
||||
// UUID, Name, TimeStampTerse);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
|
||||
//update information (timestamp, actorID, etc) needed for synchronization across copies of Scene
|
||||
SyncInfoUpdate();
|
||||
|
||||
//end of SYMMETRIC SYNC
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3130,6 +3144,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
ClearUpdateSchedule();
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
|
||||
m_parentGroup.Scene.RegionSyncModule.QueueSceneObjectPartForUpdate(this);
|
||||
|
||||
//end of SYMMETRIC SYNC
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -4888,5 +4908,208 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
#endregion
|
||||
|
||||
#region SYMMETRIC SYNC
|
||||
|
||||
//Time stamp for the most recent update on this prim. We only have one time-stamp per prim for now.
|
||||
//The goal is to evetually have time-stamp per property bucket for each prim.
|
||||
private long m_lastUpdateTimeStamp = DateTime.Now.Ticks;
|
||||
public long LastUpdateTimeStamp
|
||||
{
|
||||
get { return m_lastUpdateTimeStamp; }
|
||||
set { m_lastUpdateTimeStamp = value; }
|
||||
}
|
||||
|
||||
//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_lastUpdateActorID;
|
||||
public string LastUpdateActorID
|
||||
{
|
||||
get { return m_lastUpdateActorID; }
|
||||
set { m_lastUpdateActorID = value; }
|
||||
}
|
||||
|
||||
public void UpdateTimestamp()
|
||||
{
|
||||
m_lastUpdateTimeStamp = DateTime.Now.Ticks;
|
||||
}
|
||||
|
||||
public void SetLastUpdateActorID()
|
||||
{
|
||||
if (m_parentGroup != null)
|
||||
{
|
||||
m_lastUpdateActorID = m_parentGroup.Scene.ActorSyncModule.ActorID;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Error("Prim " + UUID + " is not in a SceneObjectGroup yet");
|
||||
}
|
||||
}
|
||||
|
||||
public void SyncInfoUpdate()
|
||||
{
|
||||
//Trick: calling UpdateTimestamp here makes sure that when an object was received and de-serialized, before
|
||||
// its parts are linked together, neither TimeStamp or ActorID will be modified. This is because during de-serialization,
|
||||
// ScheduleFullUpdate() is called when m_parentGroup == null
|
||||
if (m_parentGroup != null)
|
||||
{
|
||||
UpdateTimestamp();
|
||||
m_lastUpdateActorID = m_parentGroup.Scene.ActorSyncModule.ActorID;
|
||||
}
|
||||
}
|
||||
|
||||
//!!!!!! -- 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_lastUpdateActorID != 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_lastUpdateActorID = 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]: ScheduleFullUpdate_SyncInfoUnchanged 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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,6 +215,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
|
||||
sceneObject.AddPart(part);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
//KittyL: 12/27/2010, added ActorID for symmetric synch model
|
||||
part.SetLastUpdateActorID();
|
||||
|
||||
// SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
|
||||
// We override that here
|
||||
if (originalLinkNum != 0)
|
||||
|
@ -324,6 +328,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
|
||||
m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
|
||||
m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
m_SOPXmlProcessors.Add("LastUpdateTimeStamp", ProcessUpdateTimeStamp);
|
||||
m_SOPXmlProcessors.Add("LastUpdateActorID", ProcessLastUpdateActorID);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
#endregion
|
||||
|
||||
#region TaskInventoryXmlProcessors initialization
|
||||
|
@ -681,6 +691,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
{
|
||||
obj.ParticleSystem = Convert.FromBase64String(reader.ReadElementContentAsString("ParticleSystem", String.Empty));
|
||||
}
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
private static void ProcessUpdateTimeStamp(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.LastUpdateTimeStamp = reader.ReadElementContentAsLong("LastUpdateTimeStamp", string.Empty);
|
||||
}
|
||||
|
||||
private static void ProcessLastUpdateActorID(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.LastUpdateActorID = reader.ReadElementContentAsString("LastUpdateActorID", string.Empty);
|
||||
}
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
#endregion
|
||||
|
||||
#region TaskInventoryXmlProcessors
|
||||
|
@ -1057,7 +1080,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
|
||||
////////// Write /////////
|
||||
|
||||
public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Dictionary<string, object>options)
|
||||
public static void SOGToXml2(XmlTextWriter writer, SceneObjectGroup sog, Dictionary<string, object> options)
|
||||
{
|
||||
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
|
||||
SOPToXml2(writer, sog.RootPart, options);
|
||||
|
@ -1159,6 +1182,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
WriteBytes(writer, "TextureAnimation", sop.TextureAnimation);
|
||||
WriteBytes(writer, "ParticleSystem", sop.ParticleSystem);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
writer.WriteElementString("LastUpdateTimeStamp", sop.LastUpdateTimeStamp.ToString());
|
||||
writer.WriteElementString("LastUpdateActorID", sop.LastUpdateActorID);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@
|
|||
AssetLoaderArgs = "assets/AssetSets.xml"
|
||||
|
||||
[Groups]
|
||||
Enabled = true
|
||||
;Enabled = true
|
||||
Enabled = false
|
||||
Module = GroupsModule
|
||||
DebugEnabled = false
|
||||
NoticesEnabled = true
|
||||
|
|
Loading…
Reference in New Issue