* Fixing serialisation properly so that inventory save/restore correctly works, and OAR save/restore works with components too.

soprefactor
unknown 2010-08-18 03:54:54 +10:00
parent a46b7dd34b
commit f73d73fcfe
11 changed files with 137 additions and 37 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,8 +648,8 @@ 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} STACK: {2}", packetObject.Pack, e.ToString(),e.StackTrace), e);
} }
} }
#endregion Packet Handling #endregion Packet Handling

View File

@ -60,17 +60,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Components
#region Implementation of IComponentManagerModule #region Implementation of IComponentManagerModule
public void CreateComponent(SceneObjectPart target, Type componentType, IComponentState state) public void CreateComponent(SceneObjectPart target, string componentType, ComponentState state)
{ {
foreach (OnCreateComponentDelegate h in OnCreateComponent.GetInvocationList()) if (OnCreateComponent != null)
{ {
IComponent x = h(componentType, state); foreach (OnCreateComponentDelegate h in OnCreateComponent.GetInvocationList())
if(x != null)
{ {
target.SetComponent(x); IComponent x = h(componentType, state);
x.SetParent(target); if (x != null)
return; {
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?"); m_log.Warn("[Components] Unable to create component " + componentType + ". No ComponentFactory was able to recognize it. Could you be missing a region module?");

View File

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

View File

@ -11,6 +11,6 @@ namespace OpenSim.Region.Framework.Scenes.Components
cmm.OnCreateComponent += CreateComponent; cmm.OnCreateComponent += CreateComponent;
} }
protected abstract IComponent CreateComponent(Type componentType, IComponentState componentState); protected abstract IComponent CreateComponent(string componentType, ComponentState componentState);
} }
} }

View File

@ -4,6 +4,7 @@ using System.Runtime.Serialization;
namespace OpenSim.Region.Framework.Scenes.Components namespace OpenSim.Region.Framework.Scenes.Components
{ {
[Serializable]
public class ComponentState : IComponentState public class ComponentState : IComponentState
{ {
private readonly Dictionary<string,Object> m_stateData = new Dictionary<string,object>(); private readonly Dictionary<string,Object> m_stateData = new Dictionary<string,object>();

View File

@ -16,7 +16,7 @@ namespace OpenSim.Region.Framework.Scenes.Components
/// <summary> /// <summary>
/// A representation of the current state of the component, to be deserialised later. /// A representation of the current state of the component, to be deserialised later.
/// </summary> /// </summary>
IComponentState State { get; } ComponentState State { get; }
void SetParent(SceneObjectPart part); void SetParent(SceneObjectPart part);
} }

View File

@ -4804,16 +4804,9 @@ namespace OpenSim.Region.Framework.Scenes
#region Components #region Components
[NonSerializedAttribute] // Component serialisation occurs manually. [NonSerializedAttribute] // Component serialisation occurs manually.
private Dictionary<Type, IComponent> m_components = new Dictionary<Type, IComponent>(); private Dictionary<string, IComponent> m_components = new Dictionary<string, IComponent>();
private IDictionary<Type, IComponentState> m_componentStates = new Dictionary<Type, IComponentState>(); public SerializableDictionary<string, ComponentState> ComponentStates = new SerializableDictionary<string, ComponentState>();
public void InitComponents(IDictionary<Type,IComponentState> states)
{
m_componentStates = states;
InitComponents();
}
[NonSerializedAttribute] [NonSerializedAttribute]
private bool m_componentsInit = false; private bool m_componentsInit = false;
@ -4823,15 +4816,24 @@ namespace OpenSim.Region.Framework.Scenes
if(m_componentsInit) if(m_componentsInit)
return; return;
IDictionary<Type, IComponentState> states = m_componentStates; SerializableDictionary<string, ComponentState> states = ComponentStates;
if(ParentGroup.Scene != null) if(ParentGroup.Scene != null)
{ {
m_log.Info("[COMPONENTS] Initialising components..."); m_log.Info("[COMPONENTS] Initialising components...");
IComponentManagerModule cmm = ParentGroup.Scene.RequestModuleInterface<IComponentManagerModule>(); IComponentManagerModule cmm = ParentGroup.Scene.RequestModuleInterface<IComponentManagerModule>();
foreach(KeyValuePair<Type,IComponentState> kvp in states) foreach(KeyValuePair<string,ComponentState> kvp in states)
{ {
m_log.Info("[COMPONENTS] Adding component " + kvp.Key + " to SceneObjectPart."); m_log.Info("[COMPONENTS] Adding component " + kvp.Key + " to SceneObjectPart.");
cmm.CreateComponent(this,kvp.Key,kvp.Value);
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; m_componentsInit = true;
} else } else
@ -4842,12 +4844,15 @@ namespace OpenSim.Region.Framework.Scenes
public void SaveComponents() public void SaveComponents()
{ {
foreach (KeyValuePair<Type, IComponent> keyValuePair in m_components) m_log.Info("[COMPONENTS] Saving components...");
foreach (KeyValuePair<string, IComponent> keyValuePair in m_components)
{ {
IComponentState state = keyValuePair.Value.State; ComponentState state = keyValuePair.Value.State;
Type baseType = keyValuePair.Value.BaseType; string baseType = keyValuePair.Value.BaseType.ToString();
m_componentStates[baseType] = state; m_log.Info("[COMPONENTS] Saving component " + baseType);
ComponentStates[baseType] = state;
} }
} }
@ -4868,7 +4873,7 @@ namespace OpenSim.Region.Framework.Scenes
public bool TryGet<T>(out T val) public bool TryGet<T>(out T val)
{ {
if(m_components.ContainsKey(typeof(T))) if(m_components.ContainsKey(typeof(T).ToString()))
{ {
val = Get<T>(); val = Get<T>();
return true; return true;
@ -4880,13 +4885,13 @@ namespace OpenSim.Region.Framework.Scenes
public bool Contains<T>() public bool Contains<T>()
{ {
return m_components.ContainsKey(typeof (T)); return m_components.ContainsKey(typeof (T).ToString());
} }
public void SetComponent(IComponent val) public void SetComponent(IComponent val)
{ {
Type T = val.BaseType; Type T = val.BaseType;
m_components[T] = val; m_components[T.ToString()] = val;
} }
#endregion #endregion
} }

View File

@ -288,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

@ -6,7 +6,10 @@ using OpenSim.Region.Framework.Scenes.Components;
namespace OpenSim.Region.OptionalModules.World.TestComponent namespace OpenSim.Region.OptionalModules.World.TestComponent
{ {
class TestComponent : IComponent /// <summary>
/// Components must be public classes
/// </summary>
public class TestComponent : IComponent
{ {
private int m_theAnswerToTheQuestionOfLifeTheUniverseAndEverything = 42; private int m_theAnswerToTheQuestionOfLifeTheUniverseAndEverything = 42;
@ -15,7 +18,15 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
#region Implementation of IComponent #region Implementation of IComponent
public TestComponent(IComponentState state) /// <summary>
/// Components MUST have a parameterless constructor
/// </summary>
public TestComponent()
{
}
public TestComponent(ComponentState state)
{ {
m_log.Info("Its alive!"); m_log.Info("Its alive!");
} }
@ -25,7 +36,7 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
get { return typeof (TestComponent); } get { return typeof (TestComponent); }
} }
public IComponentState State public ComponentState State
{ {
get get
{ {

View File

@ -20,9 +20,10 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
#region Overrides of ComponentFactory #region Overrides of ComponentFactory
protected override IComponent CreateComponent(Type componentType, IComponentState componentState) protected override IComponent CreateComponent(string componentType, ComponentState componentState)
{ {
if(componentType == typeof(TestComponent)) m_log.Info("[TestComponentFactory] Recieved CreateComponent for " + componentType);
if(componentType == typeof(TestComponent).ToString())
{ {
string tmp; string tmp;
if(componentState.TryGet("Hello", out tmp)) if(componentState.TryGet("Hello", out tmp))
@ -97,6 +98,8 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
} }
} }
InitComponentHandler(m_scenes[0]);
m_log.Info("[TESTCOMPONENT] Test factory loaded"); m_log.Info("[TESTCOMPONENT] Test factory loaded");
} }