Compare commits

...

10 Commits

Author SHA1 Message Date
unknown e2d5ae87fd Merge remote branch 'origin' into soprefactor 2010-08-18 07:20:29 +10:00
unknown daa0d83e3a * Removed ComponentState class
* We now store component state information as a OSDMap
2010-08-18 06:45:08 +10:00
unknown 13079df156 Merge remote branch 'origin' into soprefactor 2010-08-18 05:05:58 +10:00
unknown 64547c23ad * Some minor cleanups
* Will commit the next set of changes tommorow containing the RegionData changes for permanently storing ComponentState data (n.b. they currently save/load via the ToXml/FromXml methods used by OARs and Inventory fine).
* This is very spammy code, but will attach a component to every SOP in every scene on startup. The source for the component can be seen in TestComponent - a more detailed example is coming soon.
2010-08-18 04:04:16 +10:00
unknown f73d73fcfe * Fixing serialisation properly so that inventory save/restore correctly works, and OAR save/restore works with components too. 2010-08-18 03:54:54 +10:00
unknown a46b7dd34b * 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)
2010-08-18 00:54:52 +10:00
unknown 553f99027d Merge remote branch 'origin' into soprefactor 2010-08-17 15:28:43 +10:00
Melanie 4f6e4c7b5b Fix scripts in rezzed objects not starting (Mantis #4775) 2010-06-30 21:29:28 +01:00
unknown 9ff5868910 * Removing test file. Woot. 2010-06-14 19:19:38 +10:00
unknown 952c69ae56 * Testing soprefactor branch (and that I can commit to it correctly.) 2010-06-14 19:18:38 +10:00
12 changed files with 511 additions and 5 deletions

View File

@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Xml.Serialization;
namespace OpenSim.Framework
{
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
}
}

View File

@ -648,7 +648,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
// Make sure that we see any exception caused by the asynchronous operation. // Make sure that we see any exception caused by the asynchronous operation.
m_log.Error( m_log.Error(
string.Format("[LLCLIENTVIEW]: Caught exception while processing {0}", packetObject.Pack), e); string.Format("[LLCLIENTVIEW]: Caught exception while processing {0} {1}", packetObject.Pack, e.ToString()), e);
} }
} }

View File

@ -552,9 +552,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// process causes some clients to fail to display the attachment properly. // process causes some clients to fail to display the attachment properly.
m_Scene.AddNewSceneObject(group, true, false); 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); // 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 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) if (!attachment)
{ {
group.ScheduleGroupForFullUpdate(); group.ScheduleGroupForFullUpdate();

View File

@ -0,0 +1,91 @@
using System;
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse.StructuredData;
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, string componentType, OSDMap state)
{
if (OnCreateComponent != null)
{
foreach (OnCreateComponentDelegate h in OnCreateComponent.GetInvocationList())
{
IComponent x = h(componentType, state);
if (x != null)
{
target.SetComponent(x);
x.SetParent(target);
return;
}
}
} else
{
m_log.Warn("[Components] No component handlers loaded. Are you missing a region module?");
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,15 @@
using System;
using OpenMetaverse.StructuredData;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.Framework.Interfaces
{
public delegate IComponent OnCreateComponentDelegate(string componentType, OSDMap componentState);
public interface IComponentManagerModule
{
void CreateComponent(SceneObjectPart part, string componentType, OSDMap state);
event OnCreateComponentDelegate OnCreateComponent;
}
}

View File

@ -0,0 +1,17 @@
using System;
using OpenMetaverse.StructuredData;
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(string componentType, OSDMap componentState);
}
}

View File

@ -0,0 +1,24 @@
using System;
using OpenMetaverse.StructuredData;
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>
OSDMap State { get; }
void SetParent(SceneObjectPart part);
}
}

View File

@ -568,6 +568,8 @@ namespace OpenSim.Region.Framework.Scenes
ApplyPhysics(m_scene.m_physicalPrim); ApplyPhysics(m_scene.m_physicalPrim);
InitPartComponents();
// Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled // 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. // for the same object with very different properties. The caller must schedule the update.
//ScheduleGroupForFullUpdate(); //ScheduleGroupForFullUpdate();
@ -1133,6 +1135,8 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="scene"></param> /// <param name="scene"></param>
public void SetScene(Scene scene) public void SetScene(Scene scene)
{ {
InitPartComponents();
m_scene = scene; m_scene = scene;
} }
@ -3579,6 +3583,17 @@ 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 #region ISceneObject
public virtual ISceneObject CloneForNewScene() public virtual ISceneObject CloneForNewScene()

View File

@ -30,14 +30,15 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Reflection; using System.Reflection;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Xml; using System.Xml;
using System.Xml.Serialization; using System.Xml.Serialization;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Components;
using OpenSim.Region.Framework.Scenes.Scripting; using OpenSim.Region.Framework.Scenes.Scripting;
using OpenSim.Region.Physics.Manager; using OpenSim.Region.Physics.Manager;
@ -3492,6 +3493,8 @@ namespace OpenSim.Region.Framework.Scenes
public void SetParent(SceneObjectGroup parent) public void SetParent(SceneObjectGroup parent)
{ {
m_parentGroup = parent; m_parentGroup = parent;
InitComponents();
} }
// Use this for attachments! LocalID should be avatar's localid // Use this for attachments! LocalID should be avatar's localid
@ -4053,6 +4056,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="xmlWriter"></param> /// <param name="xmlWriter"></param>
public void ToXml(XmlWriter xmlWriter) public void ToXml(XmlWriter xmlWriter)
{ {
SaveComponents(); // Gather all the component data
serializer.Serialize(xmlWriter, this); serializer.Serialize(xmlWriter, this);
} }
@ -4797,5 +4801,106 @@ namespace OpenSim.Region.Framework.Scenes
Color color = Color; Color color = Color;
return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
} }
#region Components
[NonSerializedAttribute] // Component serialisation occurs manually.
private Dictionary<string, IComponent> m_components = new Dictionary<string, IComponent>();
public SerializableDictionary<string, string> ComponentStates = new SerializableDictionary<string, string>();
[NonSerializedAttribute]
private bool m_componentsInit = false;
public void InitComponents()
{
if(m_componentsInit)
return;
Dictionary<string,OSDMap> states = new Dictionary<string, OSDMap>();
foreach (KeyValuePair<string, string> componentState in ComponentStates)
{
states.Add(componentState.Key, OSDParser.DeserializeJson(componentState.Value) as OSDMap);
}
//SerializableDictionary<string, OSDMap> states = ComponentStates;
if(ParentGroup.Scene != null)
{
m_log.Info("[COMPONENTS] Initialising components...");
IComponentManagerModule cmm = ParentGroup.Scene.RequestModuleInterface<IComponentManagerModule>();
foreach (KeyValuePair<string, OSDMap> kvp in states)
{
m_log.Info("[COMPONENTS] Adding component " + kvp.Key + " to SceneObjectPart.");
try
{
cmm.CreateComponent(this, kvp.Key, kvp.Value);
}
catch(Exception e)
{
m_log.Error("Error creating component " + e.ToString());
m_log.Error("Stacktrace: " + e.StackTrace);
}
}
m_componentsInit = true;
} else
{
m_log.Warn("[COMPONENTS] Trying to initialise component which is not attached to a scene.");
}
}
public void SaveComponents()
{
m_log.Info("[COMPONENTS] Saving components...");
foreach (KeyValuePair<string, IComponent> keyValuePair in m_components)
{
OSDMap state = keyValuePair.Value.State;
string baseType = keyValuePair.Value.BaseType.ToString();
m_log.Info("[COMPONENTS] Saving component " + baseType);
ComponentStates[baseType] = OSDParser.SerializeJsonString(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).ToString()))
{
val = Get<T>();
return true;
}
val = default(T);
return false;
}
public bool Contains<T>()
{
return m_components.ContainsKey(typeof (T).ToString());
}
public void SetComponent(IComponent val)
{
Type T = val.BaseType;
m_components[T.ToString()] = 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 // Script state may, or may not, exist. Not having any, is NOT
// ever a problem. // ever a problem.
sceneObject.LoadScriptState(doc); sceneObject.LoadScriptState(doc);
sceneObject.InitPartComponents();
return sceneObject; return sceneObject;
} }
@ -240,6 +241,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
// ever a problem. // ever a problem.
sceneObject.LoadScriptState(doc); sceneObject.LoadScriptState(doc);
sceneObject.InitPartComponents();
return sceneObject; return sceneObject;
} }
catch (Exception e) catch (Exception e)
@ -285,6 +288,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
{ {
foreach (SceneObjectPart part in sceneObject.Children.Values) foreach (SceneObjectPart part in sceneObject.Children.Values)
{ {
part.SaveComponents();
if (part.UUID != sceneObject.RootPart.UUID) if (part.UUID != sceneObject.RootPart.UUID)
{ {
part.ToXml(writer); part.ToXml(writer);

View File

@ -0,0 +1,56 @@
using System;
using System.Reflection;
using log4net;
using OpenMetaverse.StructuredData;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.OptionalModules.World.TestComponent
{
/// <summary>
/// Components must be public classes
/// </summary>
public 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()
{
m_log.Info("Its alive! (for the very first time...!)");
}
public TestComponent(OSDMap state)
{
m_log.Info("Its alive!");
}
public Type BaseType
{
get { return typeof (TestComponent); }
}
public OSDMap State
{
get
{
OSDMap x = new OSDMap();
x["Hello"] = "World";
x["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,104 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse.StructuredData;
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(string componentType, OSDMap componentState)
{
m_log.Info("[TestComponentFactory] Recieved CreateComponent for " + componentType);
if(componentType == typeof(TestComponent).ToString())
{
if(componentState.ContainsKey("Hello"))
{
m_log.Info("[TestComponentFactory] Successfully recovered '" + componentState["Hello"] + "' 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());
}
}
}
InitComponentHandler(m_scenes[0]);
m_log.Info("[TESTCOMPONENT] Test factory loaded");
}
#endregion
}
}