|
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Reflection;
- using System.Xml;
- using SUISS.Core;
- using SUISS.Core.Utilities;
- using SUISS.Storage;
- using UnityEngine;
-
- namespace Engine.DependencyTree
- {
- public sealed class DependencyTree : SingletonMonobehaviour<DependencyTree>
- {
- //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
- public event Dependency.AchievedChangedEventHandler DependencyAchievedChangedEvent;
-
- //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
- public event Dependency.ActiveChangedEventHandler DependencyActiveChangedEvent;
-
- //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
- public event Dependency.RewardClaimedEventHandler DependencyRewardClaimedEvent;
-
- protected override void Awake()
- {
- base.Awake();
- if (!this._isValidNewInstance)
- {
- return;
- }
- this._mutating = 0;
- this._persistentState = Storage.Get(this.storageLifecycle).GetDictionary(this.storageKey);
- this._communicator = new DependencyTree.CommunicatorInstance(this);
- this._cache = new Dictionary<string, Dependency>();
- this._templates = new Dictionary<string, DependencyTemplate>();
- this._treeState = DependencyState.Created;
- this.BeginMutating();
- try
- {
- this._root = this.CreateDependency("root", null);
- this._cache[this._root.Identifier] = this._root;
- if (this.treeXML != null)
- {
- this.ParseTreeXML(this.treeXML.text);
- }
- }
- finally
- {
- this.EndMutating();
- }
- }
-
- private void Start()
- {
- this._treeState = DependencyState.Started;
- this.Traverse(delegate(Dependency dependency)
- {
- if (dependency.State == DependencyState.Created)
- {
- dependency.OnStart();
- }
- });
- }
-
- protected override void OnDestroy()
- {
- base.OnDestroy();
- this._treeState = DependencyState.Destroyed;
- this.Traverse(delegate(Dependency dependency)
- {
- if (dependency.State != DependencyState.Destroyed)
- {
- dependency.OnDestroy();
- }
- });
- }
-
- public Dependency Root
- {
- get
- {
- return this._root;
- }
- }
-
- public Dependency this[string identifier]
- {
- get
- {
- if (identifier == null)
- {
- throw new ArgumentNullException("identifier");
- }
- Dependency result;
- if (this._cache.TryGetValue(identifier, out result))
- {
- return result;
- }
- throw new KeyNotFoundException("No dependency with identifier " + identifier + " exists.");
- }
- }
-
- public bool IsMutating
- {
- get
- {
- return this._mutating > 0;
- }
- }
-
- public bool ContainsDependency(string identifier)
- {
- if (identifier == null)
- {
- throw new ArgumentNullException("identifier");
- }
- return this._cache.ContainsKey(identifier);
- }
-
- public bool TryGetDependency(string identifier, out Dependency dependency)
- {
- if (identifier == null)
- {
- throw new ArgumentNullException("identifier");
- }
- return this._cache.TryGetValue(identifier, out dependency);
- }
-
- public bool ContainsTemplate(string identifier)
- {
- if (identifier == null)
- {
- throw new ArgumentNullException("identifier");
- }
- return this._templates.ContainsKey(identifier);
- }
-
- public DependencyTemplate GetTemplate(string identifier)
- {
- if (identifier == null)
- {
- throw new ArgumentNullException("identifier");
- }
- return this._templates[identifier];
- }
-
- public bool TryGetTemplate(string identifier, out DependencyTemplate template)
- {
- if (identifier == null)
- {
- throw new ArgumentNullException("identifier");
- }
- return this._templates.TryGetValue(identifier, out template);
- }
-
- public void BeginMutating()
- {
- this._mutating++;
- if (this._mutating == 1)
- {
- this._dependencyTypeCache = new Dictionary<string, ConstructorInfo>();
- this.Traverse(delegate(Dependency dependency)
- {
- dependency.OnBeginMutating();
- });
- }
- }
-
- public void EndMutating()
- {
- if (this._mutating == 1)
- {
- this.Traverse(delegate(Dependency dependency)
- {
- dependency.OnEndMutating();
- });
- this._dependencyTypeCache = null;
- }
- this._mutating--;
- }
-
- public Dependency CreateDependency(string identifier, Dictionary<string, string> properties)
- {
- return this.CreateDependency(identifier, properties, null);
- }
-
- public Dependency CreateDependency(string identifier, Dictionary<string, string> properties, string className)
- {
- this.EnsureMutating();
- if (className == null)
- {
- className = typeof(Dependency).FullName;
- }
- ConstructorInfo constructor;
- if (!this._dependencyTypeCache.TryGetValue(className, out constructor))
- {
- Type type = null;
- try
- {
- type = Type.GetType(className);
- }
- catch (Exception ex)
- {
- UnityEngine.Debug.LogError("Exception while trying to resolve type from string '" + className + "': " + ex.ToString());
- }
- if (type == null)
- {
- UnityEngine.Debug.LogError("Could not resolve type from string '" + className + "'. This is probably a big error.");
- return null;
- }
- if (!typeof(Dependency).GetCompatibleTypeInfo().IsAssignableFrom(type.GetCompatibleTypeInfo()))
- {
- UnityEngine.Debug.LogError("Type '" + className + "' is not a subclass of Dependency. This is probably a big error.");
- return null;
- }
- Type[] types = new Type[]
- {
- typeof(string),
- typeof(Dictionary<string, object>),
- typeof(Dictionary<string, string>),
- typeof(DependencyTree.Communicator)
- };
- constructor = type.GetConstructor(types);
- if (constructor == null)
- {
- UnityEngine.Debug.LogError("Dependency type '" + className + "' does not have a constructor in the form (string, Dictionary<string, object>, Dictionary<string, string>, DependencyTree.Communicator). Defaulting to type Dependency, but this is probably a big error.");
- constructor = typeof(Dependency).GetConstructor(types);
- }
- this._dependencyTypeCache[className] = constructor;
- }
- object[] parameters = new object[]
- {
- identifier,
- this.GetDependencyPersistentState(identifier),
- properties,
- this._communicator
- };
- return (Dependency)constructor.Invoke(parameters);
- }
-
- public void Traverse(Dependency.Traverser traverser)
- {
- if (this._root != null)
- {
- this._root.Traverse(traverser);
- }
- }
-
- private void OnSubTreeAttached(Dependency parent, Dependency child)
- {
- this.EnsureMutating();
- this.AddToCache(child);
- if (this._treeState == DependencyState.Destroyed)
- {
- child.Traverse(delegate(Dependency c)
- {
- if (c.State != DependencyState.Destroyed)
- {
- c.OnDestroy();
- }
- });
- }
- else if (this._treeState == DependencyState.Started)
- {
- child.Traverse(delegate(Dependency c)
- {
- if (c.State == DependencyState.Created)
- {
- c.OnStart();
- }
- });
- }
- }
-
- private void OnSubTreeDetached(Dependency parent, Dependency child)
- {
- this.EnsureMutating();
- this.RemoveFromCache(child);
- }
-
- private void OnSubTreeAchievedChanged(Dependency subTree, bool achieved)
- {
- this.FireDependencyAchievedChangedEvent(subTree, achieved);
- }
-
- private void OnDependencyActiveChanged(Dependency dependency, bool active)
- {
- this.FireDependencyActiveChangedEvent(dependency, active);
- }
-
- private void OnDependencyRewardClaimed(Dependency dependency, bool claimed)
- {
- this.FireDependencyRewardClaimedEvent(dependency, claimed);
- }
-
- private void FireDependencyAchievedChangedEvent(Dependency dependency, bool achieved)
- {
- if (this.DependencyAchievedChangedEvent != null)
- {
- this.DependencyAchievedChangedEvent(dependency, achieved);
- }
- }
-
- private void FireDependencyActiveChangedEvent(Dependency dependency, bool active)
- {
- if (this.DependencyActiveChangedEvent != null)
- {
- this.DependencyActiveChangedEvent(dependency, active);
- }
- }
-
- private void FireDependencyRewardClaimedEvent(Dependency dependency, bool claimed)
- {
- if (this.DependencyRewardClaimedEvent != null)
- {
- this.DependencyRewardClaimedEvent(dependency, claimed);
- }
- }
-
- private Dictionary<string, object> GetDependencyPersistentState(string identifier)
- {
- if (identifier == null)
- {
- return null;
- }
- object obj;
- if (this._persistentState.TryGetValue(identifier, out obj) && obj is Dictionary<string, object>)
- {
- return (Dictionary<string, object>)obj;
- }
- Dictionary<string, object> dictionary = new Dictionary<string, object>();
- this._persistentState[identifier] = dictionary;
- return dictionary;
- }
-
- private void EnsureMutating()
- {
- if (this._mutating <= 0)
- {
- throw new InvalidOperationException("Can't mutate DependencyTree outside of calls to BeginMutate() and EndMutate().");
- }
- }
-
- private void ParseTreeXML(string xml)
- {
- XmlDocument xmlDocument = new XmlDocument();
- xmlDocument.XmlResolver = null;
- xmlDocument.LoadXml(xml);
- XmlNode lastChild = xmlDocument.LastChild;
- if (lastChild.Name != "dependency-tree")
- {
- throw new FormatException("Missing root <dependency-tree> node.");
- }
- this.BeginMutating();
- try
- {
- Dictionary<string, string> dictionary = new Dictionary<string, string>();
- IEnumerator enumerator = lastChild.GetEnumerator();
- try
- {
- while (enumerator.MoveNext())
- {
- object obj = enumerator.Current;
- XmlNode xmlNode = (XmlNode)obj;
- if (xmlNode.Name == "class-shortcut")
- {
- string text = null;
- XmlAttribute xmlAttribute = xmlNode.Attributes["name"];
- if (xmlAttribute != null)
- {
- text = xmlAttribute.Value;
- if (text.Length == 0)
- {
- text = null;
- }
- }
- if (text == null)
- {
- throw new FormatException("Class-shortcut node is missing a 'name' attribute.");
- }
- string innerText = xmlNode.InnerText;
- if (string.IsNullOrEmpty(innerText))
- {
- throw new FormatException("Class-shortcut node is missing a class name as its InnerText.");
- }
- dictionary[text] = innerText;
- }
- else if (xmlNode.Name == "dependency")
- {
- this.ParseDependencyXmlNode(this._root, xmlNode, dictionary);
- }
- else if (xmlNode.Name == "template")
- {
- this.ParseTemplateXmlNode(this._root, xmlNode, dictionary);
- }
- }
- }
- finally
- {
- IDisposable disposable;
- if ((disposable = (enumerator as IDisposable)) != null)
- {
- disposable.Dispose();
- }
- }
- }
- finally
- {
- this.EndMutating();
- }
- }
-
- private void ParseDependencyXmlNode(Dependency parent, XmlNode node, Dictionary<string, string> classShortcuts)
- {
- string text = null;
- XmlAttribute xmlAttribute = node.Attributes["id"];
- if (xmlAttribute != null)
- {
- text = xmlAttribute.Value;
- if (text.Length == 0)
- {
- text = null;
- }
- }
- string text2 = null;
- xmlAttribute = node.Attributes["class"];
- if (xmlAttribute != null)
- {
- text2 = xmlAttribute.Value;
- if (text2.Length == 0)
- {
- text2 = null;
- }
- }
- if (text2 != null && classShortcuts.ContainsKey(text2))
- {
- text2 = classShortcuts[text2];
- }
- Dictionary<string, string> dictionary = null;
- List<XmlNode> list = null;
- List<XmlNode> list2 = null;
- IEnumerator enumerator = node.GetEnumerator();
- try
- {
- while (enumerator.MoveNext())
- {
- object obj = enumerator.Current;
- XmlNode xmlNode = (XmlNode)obj;
- if (xmlNode.Name == "property")
- {
- if (dictionary == null)
- {
- dictionary = new Dictionary<string, string>();
- }
- KeyValuePair<string, string> keyValuePair = this.ParsePropertyXmlNode(xmlNode);
- if (dictionary.ContainsKey(keyValuePair.Key))
- {
- throw new FormatException(string.Concat(new string[]
- {
- "Dependency '",
- text,
- "' contains a duplicate property '",
- keyValuePair.Key,
- "'."
- }));
- }
- dictionary[keyValuePair.Key] = keyValuePair.Value;
- }
- else if (xmlNode.Name == "dependency")
- {
- if (list == null)
- {
- list = new List<XmlNode>();
- }
- list.Add(xmlNode);
- }
- else if (xmlNode.Name == "template")
- {
- if (list2 == null)
- {
- list2 = new List<XmlNode>();
- }
- list2.Add(xmlNode);
- }
- }
- }
- finally
- {
- IDisposable disposable;
- if ((disposable = (enumerator as IDisposable)) != null)
- {
- disposable.Dispose();
- }
- }
- Dependency dependency = this.CreateDependency(text, dictionary, text2);
- if (dependency != null)
- {
- parent.AddChild(dependency);
- if (list != null)
- {
- foreach (XmlNode node2 in list)
- {
- this.ParseDependencyXmlNode(dependency, node2, classShortcuts);
- }
- }
- if (list2 != null)
- {
- foreach (XmlNode node3 in list2)
- {
- this.ParseTemplateXmlNode(dependency, node3, classShortcuts);
- }
- }
- }
- }
-
- private void ParseTemplateXmlNode(Dependency parent, XmlNode node, Dictionary<string, string> classShortcuts)
- {
- string text = null;
- XmlAttribute xmlAttribute = node.Attributes["id"];
- if (xmlAttribute != null)
- {
- text = xmlAttribute.Value;
- if (text.Length == 0)
- {
- text = null;
- }
- }
- if (text == null)
- {
- throw new FormatException("Template node is missing an 'id' attribute.");
- }
- if (this._templates.ContainsKey(text))
- {
- throw new FormatException("A template with identifier '" + text + "' already exists.");
- }
- string text2 = null;
- xmlAttribute = node.Attributes["class"];
- if (xmlAttribute != null)
- {
- text2 = xmlAttribute.Value;
- if (text2.Length == 0)
- {
- text2 = null;
- }
- }
- if (text2 != null && classShortcuts.ContainsKey(text2))
- {
- text2 = classShortcuts[text2];
- }
- Dictionary<string, string> dictionary = new Dictionary<string, string>();
- IEnumerator enumerator = node.GetEnumerator();
- try
- {
- while (enumerator.MoveNext())
- {
- object obj = enumerator.Current;
- XmlNode xmlNode = (XmlNode)obj;
- if (xmlNode.Name == "property")
- {
- KeyValuePair<string, string> keyValuePair = this.ParsePropertyXmlNode(xmlNode);
- if (dictionary.ContainsKey(keyValuePair.Key))
- {
- throw new FormatException(string.Concat(new string[]
- {
- "Template '",
- text,
- "' contains a duplicate property '",
- keyValuePair.Key,
- "'."
- }));
- }
- dictionary[keyValuePair.Key] = keyValuePair.Value;
- }
- else if (xmlNode.Name == "dependency" || xmlNode.Name == "template")
- {
- throw new FormatException("Dependencies and templates cannot be nested within a template.");
- }
- }
- }
- finally
- {
- IDisposable disposable;
- if ((disposable = (enumerator as IDisposable)) != null)
- {
- disposable.Dispose();
- }
- }
- DependencyTemplate dependencyTemplate = new DependencyTemplate(text, text2, dictionary);
- this._templates[dependencyTemplate.Identifier] = dependencyTemplate;
- }
-
- private KeyValuePair<string, string> ParsePropertyXmlNode(XmlNode node)
- {
- string text = null;
- XmlAttribute xmlAttribute = node.Attributes["name"];
- if (xmlAttribute != null)
- {
- text = xmlAttribute.Value;
- if (text.Length == 0)
- {
- text = null;
- }
- }
- if (text == null)
- {
- throw new FormatException("Property node is missing a 'name' attribute.");
- }
- return new KeyValuePair<string, string>(text, node.InnerText);
- }
-
- private void AddToCache(Dependency dep)
- {
- if (dep.Identifier != null)
- {
- if (this._cache.ContainsKey(dep.Identifier))
- {
- throw new ArgumentException("A dependency with identifier '" + dep.Identifier + "' already exists.", "dep");
- }
- this._cache[dep.Identifier] = dep;
- }
- foreach (Dependency dep2 in dep.Children)
- {
- this.AddToCache(dep2);
- }
- }
-
- private void RemoveFromCache(Dependency dep)
- {
- if (dep.Identifier != null)
- {
- this._cache.Remove(dep.Identifier);
- }
- foreach (Dependency dep2 in dep.Children)
- {
- this.RemoveFromCache(dep2);
- }
- }
-
- public const string RootIdentifier = "root";
-
- public StorageLifecycle storageLifecycle = StorageLifecycle.Game;
-
- public string storageKey = "DependencyTree";
-
- public TextAsset treeXML;
-
- private int _mutating;
-
- private Dictionary<string, ConstructorInfo> _dependencyTypeCache;
-
- private Dictionary<string, object> _persistentState;
-
- private DependencyState _treeState;
-
- private DependencyTree.Communicator _communicator;
-
- private Dependency _root;
-
- private Dictionary<string, Dependency> _cache;
-
- private Dictionary<string, DependencyTemplate> _templates;
-
- public interface Communicator
- {
- DependencyTree Tree { get; }
-
- void NotifySubTreeAttached(Dependency parent, Dependency child);
-
- void NotifySubTreeDetached(Dependency parent, Dependency child);
-
- void NotifySubTreeAchievedChanged(Dependency subTree, bool achieved);
-
- void NotifyActiveChanged(Dependency dependency, bool active);
-
- void NotifyRewardClaimed(Dependency dependency, bool claimed);
- }
-
- private class CommunicatorInstance : DependencyTree.Communicator
- {
- public CommunicatorInstance(DependencyTree tree)
- {
- if (tree._communicator != null)
- {
- throw new InvalidOperationException("The specified tree already has a communicator.");
- }
- this._tree = tree;
- }
-
- public DependencyTree Tree
- {
- get
- {
- return this._tree;
- }
- }
-
- public void NotifySubTreeAttached(Dependency parent, Dependency child)
- {
- this._tree.OnSubTreeAttached(parent, child);
- }
-
- public void NotifySubTreeDetached(Dependency parent, Dependency child)
- {
- this._tree.OnSubTreeDetached(parent, child);
- }
-
- public void NotifySubTreeAchievedChanged(Dependency subTree, bool achieved)
- {
- this._tree.OnSubTreeAchievedChanged(subTree, achieved);
- }
-
- public void NotifyActiveChanged(Dependency dependency, bool active)
- {
- this._tree.OnDependencyActiveChanged(dependency, active);
- }
-
- public void NotifyRewardClaimed(Dependency dependency, bool claimed)
- {
- this._tree.OnDependencyRewardClaimed(dependency, claimed);
- }
-
- private DependencyTree _tree;
- }
- }
- }
|