* Adding some of the SOP Refactor code, including the base classes

* Will commit the rest later once I'm done fighting with the inventory service some more. (Figured I'd commit the major stuff before fighting with the rest)
soprefactor
unknown 2010-08-18 00:54:52 +10:00
parent 553f99027d
commit a46b7dd34b
12 changed files with 470 additions and 3 deletions

View File

@ -552,9 +552,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// process causes some clients to fail to display the attachment properly.
m_Scene.AddNewSceneObject(group, true, false);
// This is required for Group.Scene to be valid
group.SetScene(m_Scene);
// m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z);
// if attachment we set it's asset id so object updates can reflect that
// if not, we set it's position in world.
// if not, we set it's position in world.);
if (!attachment)
{
group.ScheduleGroupForFullUpdate();

View File

@ -0,0 +1,83 @@
using System;
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.CoreModules.World.Objects.Components
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ComponentManagerModule")]
class ComponentManagerModule : IComponentManagerModule, ISharedRegionModule
{
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public string Name
{
get
{
return "ComponentManager";
}
}
public Type ReplaceableInterface
{
get { return typeof (IComponentManagerModule); }
}
public void Initialise(IConfigSource source)
{
}
public void Close()
{
}
public void AddRegion(Scene scene)
{
scene.RegisterModuleInterface<IComponentManagerModule>(this);
}
public void RemoveRegion(Scene scene)
{
}
public void RegionLoaded(Scene scene)
{
}
public void PostInitialise()
{
}
#region Implementation of IComponentManagerModule
public void CreateComponent(SceneObjectPart target, Type componentType, IComponentState state)
{
foreach (OnCreateComponentDelegate h in OnCreateComponent.GetInvocationList())
{
IComponent x = h(componentType, state);
if(x != null)
{
target.SetComponent(x);
x.SetParent(target);
return;
}
}
m_log.Warn("[Components] Unable to create component " + componentType + ". No ComponentFactory was able to recognize it. Could you be missing a region module?");
}
public event OnCreateComponentDelegate OnCreateComponent;
#endregion
}
}

View File

@ -0,0 +1,14 @@
using System;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.Framework.Interfaces
{
public delegate IComponent OnCreateComponentDelegate(Type componentType, IComponentState componentState);
public interface IComponentManagerModule
{
void CreateComponent(SceneObjectPart part, Type componentType, IComponentState state);
event OnCreateComponentDelegate OnCreateComponent;
}
}

View File

@ -0,0 +1,16 @@
using System;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.Framework.Scenes.Components
{
public abstract class ComponentFactory
{
public void InitComponentHandler(Scene x)
{
IComponentManagerModule cmm = x.RequestModuleInterface<IComponentManagerModule>();
cmm.OnCreateComponent += CreateComponent;
}
protected abstract IComponent CreateComponent(Type componentType, IComponentState componentState);
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace OpenSim.Region.Framework.Scenes.Components
{
public class ComponentState : IComponentState
{
private readonly Dictionary<string,Object> m_stateData = new Dictionary<string,object>();
public void Set<T>(string name, T data)
{
if (typeof(T).IsSerializable)
{
m_stateData[name] = data;
}
else
{
throw new SerializationException("Unable to set " + name + " as value because " + typeof (T) +
" is not a serializable type.");
}
}
public bool TryGet<T>(string name, out T val)
{
Object x;
if(m_stateData.TryGetValue(name, out x))
{
if(x is T)
{
val = (T)x;
return true;
}
}
val = default(T);
return false;
}
public T Get<T>(string name)
{
return (T) m_stateData[name];
}
public string Serialise()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,23 @@
using System;
namespace OpenSim.Region.Framework.Scenes.Components
{
/// <summary>
/// A component on an object
/// TODO: Better documentation
/// </summary>
public interface IComponent
{
/// <summary>
/// The type of the component, only one of each 'type' can be loaded.
/// </summary>
Type BaseType { get; }
/// <summary>
/// A representation of the current state of the component, to be deserialised later.
/// </summary>
IComponentState State { get; }
void SetParent(SceneObjectPart part);
}
}

View File

@ -0,0 +1,18 @@
namespace OpenSim.Region.Framework.Scenes.Components
{
public interface IComponentState
{
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <param name="data">A serializable type</param>
void Set<T>(string name, T data);
T Get<T>(string name);
bool TryGet<T>(string name, out T data);
string Serialise();
}
}

View File

@ -568,6 +568,8 @@ namespace OpenSim.Region.Framework.Scenes
ApplyPhysics(m_scene.m_physicalPrim);
InitPartComponents();
// Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
// for the same object with very different properties. The caller must schedule the update.
//ScheduleGroupForFullUpdate();
@ -1133,6 +1135,8 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="scene"></param>
public void SetScene(Scene scene)
{
InitPartComponents();
m_scene = scene;
}
@ -3579,8 +3583,19 @@ namespace OpenSim.Region.Framework.Scenes
}
}
#region Components
public void InitPartComponents()
{
m_log.Info("[COMPONENTS] Initialising part components");
foreach (SceneObjectPart part in m_parts.Values)
part.InitComponents();
}
#endregion
#region ISceneObject
public virtual ISceneObject CloneForNewScene()
{
SceneObjectGroup sog = Copy(false);

View File

@ -30,7 +30,6 @@ using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Xml;
using System.Xml.Serialization;
using log4net;
@ -38,6 +37,7 @@ using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Components;
using OpenSim.Region.Framework.Scenes.Scripting;
using OpenSim.Region.Physics.Manager;
@ -3492,6 +3492,8 @@ namespace OpenSim.Region.Framework.Scenes
public void SetParent(SceneObjectGroup parent)
{
m_parentGroup = parent;
InitComponents();
}
// Use this for attachments! LocalID should be avatar's localid
@ -4053,6 +4055,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="xmlWriter"></param>
public void ToXml(XmlWriter xmlWriter)
{
SaveComponents(); // Gather all the component data
serializer.Serialize(xmlWriter, this);
}
@ -4797,5 +4800,94 @@ namespace OpenSim.Region.Framework.Scenes
Color color = Color;
return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
}
#region Components
[NonSerializedAttribute] // Component serialisation occurs manually.
private Dictionary<Type, IComponent> m_components = new Dictionary<Type, IComponent>();
private IDictionary<Type, IComponentState> m_componentStates = new Dictionary<Type, IComponentState>();
public void InitComponents(IDictionary<Type,IComponentState> states)
{
m_componentStates = states;
InitComponents();
}
[NonSerializedAttribute]
private bool m_componentsInit = false;
public void InitComponents()
{
if(m_componentsInit)
return;
IDictionary<Type, IComponentState> states = m_componentStates;
if(ParentGroup.Scene != null)
{
m_log.Info("[COMPONENTS] Initialising components...");
IComponentManagerModule cmm = ParentGroup.Scene.RequestModuleInterface<IComponentManagerModule>();
foreach(KeyValuePair<Type,IComponentState> kvp in states)
{
m_log.Info("[COMPONENTS] Adding component " + kvp.Key + " to SceneObjectPart.");
cmm.CreateComponent(this,kvp.Key,kvp.Value);
}
m_componentsInit = true;
} else
{
m_log.Warn("[COMPONENTS] Trying to initialise component which is not attached to a scene.");
}
}
public void SaveComponents()
{
foreach (KeyValuePair<Type, IComponent> keyValuePair in m_components)
{
IComponentState state = keyValuePair.Value.State;
Type baseType = keyValuePair.Value.BaseType;
m_componentStates[baseType] = state;
}
}
/// <summary>
/// Accesses a component
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T C<T>()
{
return Get<T>();
}
public T Get<T>()
{
return default(T);
}
public bool TryGet<T>(out T val)
{
if(m_components.ContainsKey(typeof(T)))
{
val = Get<T>();
return true;
}
val = default(T);
return false;
}
public bool Contains<T>()
{
return m_components.ContainsKey(typeof (T));
}
public void SetComponent(IComponent val)
{
Type T = val.BaseType;
m_components[T] = val;
}
#endregion
}
}

View File

@ -113,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
// Script state may, or may not, exist. Not having any, is NOT
// ever a problem.
sceneObject.LoadScriptState(doc);
sceneObject.InitPartComponents();
return sceneObject;
}
@ -240,6 +241,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
// ever a problem.
sceneObject.LoadScriptState(doc);
sceneObject.InitPartComponents();
return sceneObject;
}
catch (Exception e)

View File

@ -0,0 +1,46 @@
using System;
using System.Reflection;
using log4net;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.OptionalModules.World.TestComponent
{
class TestComponent : IComponent
{
private int m_theAnswerToTheQuestionOfLifeTheUniverseAndEverything = 42;
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#region Implementation of IComponent
public TestComponent(IComponentState state)
{
m_log.Info("Its alive!");
}
public Type BaseType
{
get { return typeof (TestComponent); }
}
public IComponentState State
{
get
{
ComponentState x = new ComponentState();
x.Set("Hello","World");
x.Set("HitchhikersReference", m_theAnswerToTheQuestionOfLifeTheUniverseAndEverything);
return x;
}
}
public void SetParent(SceneObjectPart part)
{
m_log.Info("My parent's name is: " + part.Name);
}
#endregion
}
}

View File

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.OptionalModules.World.TestComponent
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class TestComponentFactoryModule : ComponentFactory, ISharedRegionModule
{
private List<Scene> m_scenes = new List<Scene>();
private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#region Overrides of ComponentFactory
protected override IComponent CreateComponent(Type componentType, IComponentState componentState)
{
if(componentType == typeof(TestComponent))
{
string tmp;
if(componentState.TryGet("Hello", out tmp))
{
m_log.Info("[TestComponentFactory] Successfully recovered '" + tmp + "' from a component via serialisation.");
}
return new TestComponent(componentState);
}
return null;
}
#endregion
#region Implementation of IRegionModuleBase
public string Name
{
get { return "TestComponentFactoryModule"; }
}
public Type ReplaceableInterface
{
get { return typeof (TestComponentFactoryModule); }
}
public void Initialise(IConfigSource source)
{
m_log.Info("[TESTCOMPONENT] Loading test factory...");
}
public void Close()
{
}
public void AddRegion(Scene scene)
{
}
public void RemoveRegion(Scene scene)
{
}
public void RegionLoaded(Scene scene)
{
m_log.Info("[TESTCOMPONENT] Loading test factory for " + scene.RegionInfo.RegionName);
m_scenes.Add(scene);
}
public void PostInitialise()
{
foreach (Scene scene in m_scenes)
{
m_log.Info("[TESTCOMPONENT] Adding new test component to Scene");
List<EntityBase> sogs = scene.Entities.GetAllByType<SceneObjectGroup>();
foreach (EntityBase entityBase in sogs)
{
SceneObjectGroup sog = (SceneObjectGroup) entityBase;
m_log.Info("[TESTCOMPONENT] Adding new test component to SOG");
foreach (SceneObjectPart part in sog.GetParts())
{
m_log.Info("[TESTCOMPONENT] Adding new test component to SOP");
part.SetComponent(
new TestComponent(
new ComponentState()
)
);
}
}
}
m_log.Info("[TESTCOMPONENT] Test factory loaded");
}
#endregion
}
}