* 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.
|
||||
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
|
||||
|
|
|
@ -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?");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue