* Fixing serialisation properly so that inventory save/restore correctly works, and OAR save/restore works with components too.
parent
a46b7dd34b
commit
f73d73fcfe
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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?");
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue