* 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.
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

View File

@ -60,17 +60,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Components
#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);
if(x != null)
foreach (OnCreateComponentDelegate h in OnCreateComponent.GetInvocationList())
{
target.SetComponent(x);
x.SetParent(target);
return;
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?");

View File

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

View File

@ -11,6 +11,6 @@ namespace OpenSim.Region.Framework.Scenes.Components
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
{
[Serializable]
public class ComponentState : IComponentState
{
private readonly Dictionary<string,Object> m_stateData = new Dictionary<string,object>();

View File

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

View File

@ -4804,16 +4804,9 @@ namespace OpenSim.Region.Framework.Scenes
#region Components
[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 void InitComponents(IDictionary<Type,IComponentState> states)
{
m_componentStates = states;
InitComponents();
}
public SerializableDictionary<string, ComponentState> ComponentStates = new SerializableDictionary<string, ComponentState>();
[NonSerializedAttribute]
private bool m_componentsInit = false;
@ -4823,15 +4816,24 @@ namespace OpenSim.Region.Framework.Scenes
if(m_componentsInit)
return;
IDictionary<Type, IComponentState> states = m_componentStates;
SerializableDictionary<string, ComponentState> states = ComponentStates;
if(ParentGroup.Scene != null)
{
m_log.Info("[COMPONENTS] Initialising components...");
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.");
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;
} else
@ -4842,12 +4844,15 @@ namespace OpenSim.Region.Framework.Scenes
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;
Type baseType = keyValuePair.Value.BaseType;
ComponentState state = keyValuePair.Value.State;
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)
{
if(m_components.ContainsKey(typeof(T)))
if(m_components.ContainsKey(typeof(T).ToString()))
{
val = Get<T>();
return true;
@ -4880,13 +4885,13 @@ namespace OpenSim.Region.Framework.Scenes
public bool Contains<T>()
{
return m_components.ContainsKey(typeof (T));
return m_components.ContainsKey(typeof (T).ToString());
}
public void SetComponent(IComponent val)
{
Type T = val.BaseType;
m_components[T] = val;
m_components[T.ToString()] = val;
}
#endregion
}

View File

@ -288,6 +288,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
{
foreach (SceneObjectPart part in sceneObject.Children.Values)
{
part.SaveComponents();
if (part.UUID != sceneObject.RootPart.UUID)
{
part.ToXml(writer);

View File

@ -6,7 +6,10 @@ using OpenSim.Region.Framework.Scenes.Components;
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;
@ -15,7 +18,15 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
#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!");
}
@ -25,7 +36,7 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
get { return typeof (TestComponent); }
}
public IComponentState State
public ComponentState State
{
get
{

View File

@ -20,9 +20,10 @@ namespace OpenSim.Region.OptionalModules.World.TestComponent
#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;
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");
}