Exemplo n.º 1
0
        internal static object NodeToType(Type type, YamlNode node)
        {
            // special snowflake string
            if (type == typeof(String))
            {
                return(node.ToString());
            }

            // val primitives
            if (type.IsPrimitive)
            {
                return(StringToType(type, node.ToString()));
            }

            // val enum
            if (type.IsEnum)
            {
                return(Enum.Parse(type, node.ToString()));
            }

            // custom TypeSerializer
            if (_typeSerializers.TryGetValue(type, out var serializer))
            {
                return(serializer.NodeToType(type, node));
            }

            // other val (struct)
            if (type.IsValueType)
            {
                return(_structSerializer.NodeToType(type, (YamlMappingNode)node));
            }

            throw new ArgumentException($"Type {type.FullName} is not supported.", nameof(type));
        }
Exemplo n.º 2
0
        private static object GetValue(YamlNode value)
        {
            var collection = value as YamlMappingNode;

            if (collection != null)
            {
                var results = new Dictionary <string, object>();
                foreach (var entry in collection.Children)
                {
                    var node = entry.Key as YamlScalarNode;
                    if (node != null)
                    {
                        results.Add(node.Value, GetValue(entry.Value));
                    }
                }

                return(results);
            }

            var list = value as YamlSequenceNode;

            if (list != null)
            {
                if (list.Children.All(_ => _ is YamlScalarNode))
                {
                    var listString = new List <string>();
                    foreach (var entry in list.Children)
                    {
                        var node = entry as YamlScalarNode;
                        if (node != null)
                        {
                            listString.Add(node.Value);
                        }
                    }
                    return(listString);
                }
                else
                {
                    var listResults = new List <object>();
                    foreach (var entry in list.Children)
                    {
                        listResults.Add(GetValue(entry));
                    }
                    return(listResults);
                }
            }

            bool valueBool;

            if (bool.TryParse(value.ToString(), out valueBool))
            {
                return(valueBool);
            }

            return(value.ToString());
        }
Exemplo n.º 3
0
        public InvCategory(YamlNode key, YamlNode node)
        {
            categoryID = Int32.Parse(key.ToString());
            YamlMappingNode mapping = (YamlMappingNode)node;

            foreach (var entry in mapping.Children)
            {
                string paramName = entry.Key.ToString();
                switch (paramName)
                {
                case "name":
                    name = YamlUtils.GetLanguageString(YamlUtils.GetLanguageStrings(entry.Value), UserData.language);
                    break;

                case "iconID":
                    iconID = Int32.Parse(entry.Value.ToString());
                    break;

                case "published":
                    published = Boolean.Parse(entry.Value.ToString());
                    break;

                default:
                    System.Diagnostics.Debug.WriteLine("InvCategory unknown value:" + entry.Key + " = " + entry.Value);
                    break;
                }
            }
            categories[categoryID] = this;
        }
        private void LoadYamlNode(YamlNode node)
        {
            switch (node.NodeType)
            {
            case YamlNodeType.Alias:
                // YamlDotNet replaces aliases with the anchor value, so no need to handle aliases here
                break;

            case YamlNodeType.Mapping:
                this.LoadYamlMapping((YamlMappingNode)node);
                break;

            case YamlNodeType.Scalar:
                if (this.Data.ContainsKey(this.path))
                {
                    throw new FormatException($"Duplicate configuration key '{this.path}'.");
                }

                this.Data[this.path] = node.ToString();
                break;

            case YamlNodeType.Sequence:
                this.LoadYamlSequence((YamlSequenceNode)node);
                break;
            }
        }
Exemplo n.º 5
0
        public string GetString(string path)
        {
            string[] splitPath = path.Split('.');

            YamlMappingNode currentNode = _rootNode;

            for (int i = 0; i < splitPath.Length - 1; i++)
            {
                YamlNode outputNode = null;
                currentNode.Children.TryGetValue(new YamlScalarNode(splitPath[i]), out outputNode);

                if (outputNode == null)
                {
                    return(null);
                }
                else
                {
                    currentNode = (YamlMappingNode)outputNode;
                }
            }

            YamlNode lastNode = null;

            currentNode.Children.TryGetValue(new YamlScalarNode(splitPath[splitPath.Length - 1]), out lastNode);

            if (lastNode == null)
            {
                return(null);
            }
            else
            {
                return(lastNode.ToString());
            }
        }
Exemplo n.º 6
0
        private static void SetColorValue(Component component, PropertyInfo property, YamlNode yamlNode)
        {
            PropertyInfo colorInfo = typeof(Color).GetProperty(yamlNode.ToString());
            Color        res       = (Color)colorInfo.GetValue(null, null);

            property.SetValue(component, res);
        }
Exemplo n.º 7
0
        public IconID(YamlNode key, YamlNode node)
        {
            iconID = Int32.Parse(key.ToString());
            YamlMappingNode mapping = (YamlMappingNode)node;

            foreach (var entry in mapping.Children)
            {
                string paramName = entry.Key.ToString();
                switch (paramName)
                {
                case "description":
                    description = entry.Value.ToString();
                    break;

                case "iconFile":
                    iconFile = entry.Value.ToString();
                    break;

                default:
                    System.Diagnostics.Debug.WriteLine("IconID unknown value:" + entry.Key + " = " + entry.Value);
                    break;
                }
            }
            icons[iconID] = this;
        }
Exemplo n.º 8
0
        public Blueprint(YamlNode key, YamlNode node)
        {
            blueprintTypeID = Int32.Parse(key.ToString());
            YamlMappingNode mapping = (YamlMappingNode)node;

            foreach (var entry in mapping.Children)
            {
                string paramName = entry.Key.ToString();
                switch (paramName)
                {
                case "blueprintTypeID":
                    blueprintTypeID = Int32.Parse(entry.Value.ToString());
                    break;

                case "maxProductionLimit":
                    maxProductionLimit = Int32.Parse(entry.Value.ToString());
                    break;

                case "activities":
                    YamlMappingNode activityMap = (YamlMappingNode)entry.Value;
                    foreach (var activity in activityMap.Children)
                    {
                        string traitName = activity.Key.ToString();
                        switch (traitName)
                        {
                        case "copying":
                            copying = new Activity(activity.Value);
                            break;

                        case "invention":
                            invention = new Activity(activity.Value);
                            break;

                        case "manufacturing":
                            manufacturing = new Activity(activity.Value);
                            break;

                        case "research_material":
                            research_material = new Activity(activity.Value);
                            break;

                        case "research_time":
                            research_time = new Activity(activity.Value);
                            break;

                        default:
                            System.Diagnostics.Debug.WriteLine("Blueprint unknown activity:" + activity.Key + " = " + activity.Value);
                            break;
                        }
                    }
                    break;

                default:
                    System.Diagnostics.Debug.WriteLine("Blueprint unknown value:" + entry.Key + " = " + entry.Value);
                    break;
                }
            }
            blueprints[blueprintTypeID] = this;
        }
Exemplo n.º 9
0
 static List <KeyPressDefinition> KeyPressDefinitions(YamlNode keyCombo)
 {
     return(keyCombo.ToString()
            .Split(',')
            .Select(GetKeyPressDefintion)
            .Where(definition => definition != null)
            .ToList());
 }
Exemplo n.º 10
0
        public override object NodeToType(Type type, YamlNode node)
        {
            var args = node.ToString().Split(',');

            var x = float.Parse(args[0], CultureInfo.InvariantCulture);
            var y = float.Parse(args[1], CultureInfo.InvariantCulture);

            return(new Vector2(x, y));
        }
Exemplo n.º 11
0
        private static object GetValue(YamlNode value)
        {
            if (value is YamlMappingNode collection)
            {
                var results = new Dictionary <string, object>();
                foreach (var entry in collection.Children)
                {
                    if (entry.Key is YamlScalarNode node)
                    {
                        results.Add(node.Value, GetValue(entry.Value));
                    }
                }
                return(results);
            }

            if (value is YamlSequenceNode list)
            {
                if (list.Children.All(_ => _ is YamlScalarNode))
                {
                    var listString = new List <string>();

                    foreach (var entry in list.Children)
                    {
                        if (entry is YamlScalarNode node)
                        {
                            listString.Add(node.Value);
                        }
                    }

                    return(listString);
                }
                else
                {
                    return(list.Children.Select(GetValue).ToList());
                }
            }

            if (bool.TryParse(value.ToString(), out var valueBool))
            {
                return(valueBool);
            }

            return(value.ToString());
        }
Exemplo n.º 12
0
 public override object NodeToType(Type type, YamlNode node)
 {
     try
     {
         return(Color.FromName(node.ToString()));
     }
     catch
     {
         return(node.AsHexColor());
     }
 }
Exemplo n.º 13
0
 private static bool ReadBool(YamlNode yamlNode)
 {
     try
     {
         return(bool.Parse(yamlNode.ToString()));
     }
     catch (Exception)
     {
         return(false);
     }
 }
Exemplo n.º 14
0
            public override object NodeToType(Type type, YamlNode node, YamlObjectSerializer serializer)
            {
                var args = node.ToString().Split(',');

                var b = float.Parse(args[0], CultureInfo.InvariantCulture);
                var l = float.Parse(args[1], CultureInfo.InvariantCulture);
                var t = float.Parse(args[2], CultureInfo.InvariantCulture);
                var r = float.Parse(args[3], CultureInfo.InvariantCulture);

                return(new Box2(l, b, r, t));
            }
Exemplo n.º 15
0
 public static Color AsColor(this YamlNode node, Color?fallback = null)
 {
     try
     {
         return(Color.FromName(node.ToString()));
     }
     catch
     {
         return(node.AsHexColor(fallback));
     }
 }
Exemplo n.º 16
0
        static object GetValue(YamlNode yamlNode)
        {
            if (yamlNode is YamlMappingNode)
            {
                return(GetMappingValue((YamlMappingNode)yamlNode));
            }

            if (yamlNode is YamlSequenceNode)
            {
                return(GetSequenceValue((YamlSequenceNode)yamlNode));
            }

            return(yamlNode.ToString());
        }
Exemplo n.º 17
0
        public InvGroup(YamlNode key, YamlNode node)
        {
            groupID = Int32.Parse(key.ToString());
            YamlMappingNode mapping = (YamlMappingNode)node;

            foreach (var entry in mapping.Children)
            {
                string paramName = entry.Key.ToString();
                switch (paramName)
                {
                case "name":
                    name = YamlUtils.GetLanguageString(YamlUtils.GetLanguageStrings(entry.Value), UserData.language);
                    break;

                case "iconID":
                    iconID = Int32.Parse(entry.Value.ToString());
                    break;

                case "categoryID":
                    categoryID = Int32.Parse(entry.Value.ToString());
                    break;

                case "published":
                    published = Boolean.Parse(entry.Value.ToString());
                    break;

                case "anchorable":
                    anchorable = Boolean.Parse(entry.Value.ToString());
                    break;

                case "anchored":
                    anchored = Boolean.Parse(entry.Value.ToString());
                    break;

                case "fittableNonSingleton":
                    fittableNonSingleton = Boolean.Parse(entry.Value.ToString());
                    break;

                case "useBasePrice":
                    useBasePrice = Boolean.Parse(entry.Value.ToString());
                    break;

                default:
                    System.Diagnostics.Debug.WriteLine("InvGroup unknown value:" + entry.Key + " = " + entry.Value);
                    break;
                }
            }
            groups[groupID] = this;
        }
Exemplo n.º 18
0
        private static IEnumerable <string> GetYamlNodeValues(YamlNode value)
        {
            var result = new List <string>();

            if (value is YamlSequenceNode list)
            {
                result.AddRange(list.Children.OfType <YamlScalarNode>().Select(node => node.Value));
            }
            else
            {
                result.Add(value.ToString());
            }

            return(result);
        }
        private static IEnumerable <string> GetYamlNodeValues(YamlNode value)
        {
            var retVal = new List <string>();
            var list   = value as YamlSequenceNode;

            if (list != null)
            {
                retVal.AddRange(list.Children.OfType <YamlScalarNode>().Select(node => node.Value));
            }
            else
            {
                retVal.Add(value.ToString());
            }

            return(retVal);
        }
Exemplo n.º 20
0
 private static object RenderYamlNodeToObject(YamlNode node)
 {
     if (node is YamlMappingNode)
     {
         return(RenderYamlMappingNodeToObject(node as YamlMappingNode));
     }
     if (node is YamlSequenceNode)
     {
         return(RenderYamlSequenceNodeToObject(node as YamlSequenceNode));
     }
     if (node is YamlScalarNode)
     {
         return(node.ToString());
     }
     throw new ArgumentOutOfRangeException($"The YamlNode provided is not defined to be processed, type: {node.GetType()}");
 }
Exemplo n.º 21
0
        private static void SetTexture2DValue(Component component, PropertyInfo property, YamlNode yamlNode)
        {
            string spriteName = yamlNode.ToString();

            // TODO: (#5) Need a better way to handle this
            if (spriteName == "MonoMyst/Rectangle")
            {
                property.SetValue(component, MGame.GraphicUtilities.Rectangle);
                return;
            }

            ContentManager content = MGame.GameServices.GetService <ContentManager> ();

            Texture2D res = content.Load <Texture2D> (spriteName);

            property.SetValue(component, res);
        }
Exemplo n.º 22
0
            private ConfigurationParameter ReadMultipleEnvironmentsConfiguredParameter(string parameterName,
                                                                                       YamlSequenceNode valueNodes, YamlNode descriptionNode)
            {
                string defaultValue = null;
                var    valueMapping = new Dictionary <ConfigurableEnvironment, string>();

                foreach (var valueNode in valueNodes.OfType <YamlMappingNode>())
                {
                    MapDefaultAndEnvironmentValues(valueNode, valueMapping, out string defaultValueIfFound);

                    if (defaultValueIfFound != null)
                    {
                        defaultValue = defaultValueIfFound;
                    }
                }

                return(new ConfigurationParameter(parameterName, defaultValue, valueMapping)
                {
                    Description = descriptionNode?.ToString()
                });
            }
Exemplo n.º 23
0
        private static object ParseYamlNodeValue(YamlNode valueNode)
        {
            if (valueNode is YamlScalarNode)
            {
                return(ParseStringValue(((YamlScalarNode)valueNode).Value));
            }
            else if (valueNode is YamlMappingNode)
            {
                Dictionary <string, object> hash = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);
                var mappingNode = valueNode as YamlMappingNode;
                foreach (var keyNode in mappingNode.Children.Keys)
                {
                    var scalarKeyNode = keyNode as YamlScalarNode;
                    if (scalarKeyNode == null)
                    {
                        // ignore
                        continue;
                    }

                    hash[scalarKeyNode.Value] = ParseYamlNodeValue(mappingNode.Children[keyNode]);
                }

                return(hash);
            }
            else if (valueNode is YamlSequenceNode)
            {
                var items = new List <object>();
                foreach (var itemNode in ((YamlSequenceNode)valueNode))
                {
                    items.Add(ParseYamlNodeValue(itemNode));
                }
                return(items);
            }
            else
            {
                throw new Exception("Unknown node: " + valueNode.ToString());
            }
        }
Exemplo n.º 24
0
        private static IEnumerable <string> GetYamlNodeValues(YamlNode value)
        {
            var retVal = new List <String>();
            var list   = value as YamlSequenceNode;

            if (list != null)
            {
                foreach (var entry in list.Children)
                {
                    var node = entry as YamlScalarNode;
                    if (node != null)
                    {
                        retVal.Add(node.Value);
                    }
                }
            }
            else
            {
                retVal.Add(value.ToString());
            }

            return(retVal);
        }
Exemplo n.º 25
0
        private static object GetValue(YamlNode value)
        {
            var collection = value as YamlMappingNode;

            if (collection != null)
            {
                var results = new Dictionary <string, object>();
                foreach (var entry in collection.Children)
                {
                    var node = entry.Key as YamlScalarNode;
                    if (node != null)
                    {
                        results.Add(node.Value, GetValue(entry.Value));
                    }
                }

                return(results);
            }

            var list = value as YamlSequenceNode;

            if (list != null)
            {
                var listResults = new List <string>();
                foreach (var entry in list.Children)
                {
                    var node = entry as YamlScalarNode;
                    if (node != null)
                    {
                        listResults.Add(node.Value);
                    }
                }
                return(listResults);
            }

            return(value.ToString());
        }
        protected internal override Component GetComponentInstance(ComponentDescription componentDescription, EntityInternal entity)
        {
            Component           component2;
            YamlNode            yamlNode = entity.TemplateAccessor.Get().YamlNode;
            ConfigComponentInfo info     = componentDescription.GetInfo <ConfigComponentInfo>();
            string keyName = info.KeyName;

            if (info.ConfigOptional && !yamlNode.HasValue(keyName))
            {
                return((Component)Activator.CreateInstance(componentDescription.ComponentType));
            }
            try
            {
                component2 = (Component)yamlNode.GetChildNode(keyName).ConvertTo(componentDescription.ComponentType);
            }
            catch (Exception exception)
            {
                TemplateAccessor accessor;
                string           str2      = !accessor.HasConfigPath() ? yamlNode.ToString() : accessor.ConfigPath;
                object[]         objArray1 = new object[] { "Error deserializing component ", componentDescription.ComponentType, " from configs, entity=", entity, ", key=", keyName, ", pathOrNode=", str2 };
                throw new Exception(string.Concat(objArray1), exception);
            }
            return(component2);
        }
Exemplo n.º 27
0
        /// <summary>
        /// Replaces the GUID and fileID, matching the oldIDs with the currentIDs
        /// </summary>
        /// <param name="linesToChange"></param>
        /// <param name="oldIDs">List of GUIDs and FileID for all classes in the previous project.</param>
        /// <param name="newIDs">List of GUIDs and FileID for all currently in the project classes.</param>
        /// <param name="scriptMappings"></param>
        /// <returns></returns>
        private string[] MigrateGUIDsAndFileIDs(string fileToChange, string[] linesToChange, List <ClassModel> oldIDs,
                                                List <ClassModel> newIDs,
                                                ref List <ScriptMapping> scriptMappings)
        {
            string sceneContent = string.Join("\r\n", linesToChange.PrepareSceneForYaml());

            YamlStream yamlStream       = new YamlStream();
            var        tempStringReader = new StringReader(sceneContent);

            yamlStream.Load(tempStringReader);
            tempStringReader.Close();
            IEnumerable <YamlDocument> yamlDocuments =
                yamlStream.Documents.Where(document => document.GetName() == "MonoBehaviour");

            foreach (YamlDocument document in yamlDocuments)
            {
                try
                {
                    YamlNode monoBehaviour = document.RootNode.GetChildren()["MonoBehaviour"];
                    YamlNode oldFileIdNode = monoBehaviour["m_Script"]["fileID"];
                    YamlNode oldGuidNode   = monoBehaviour["m_Script"]["guid"];

                    string oldFileId = oldFileIdNode.ToString();
                    string oldGuid   = oldGuidNode.ToString();

                    ClassModel oldClassModel =
                        oldIDs.FirstOrDefault(data =>
                                              data.Guid == oldGuid && data.FileID == oldFileId);
                    if (oldClassModel == null)
                    {
                        Debug.LogWarning("Could not find class for script with type, not migrating guid : " + oldGuid +
                                         " oldFileID : " + oldFileId);
                        continue;
                    }

                    ScriptMapping
                        mapping = FindMappingRecursively(newIDs, ref scriptMappings,
                                                         oldClassModel);
                    if (mapping == null)
                    {
                        Debug.LogError("mapping is null for " + oldClassModel.FullName);
                        continue;
                    }

                    ClassModel realNewClassModel =
                        newIDs.FirstOrDefault(model => model.FullName == mapping.newClassModel?.FullName);
                    if (realNewClassModel == null)
                    {
//                    Debug.LogError("mapping is null for " + oldClassModel.FullName + " could not find new guid.");
                        throw new NullReferenceException("mapping is null for " + oldClassModel.FullName +
                                                         " could not find new guid.");
                    }

                    int line = oldFileIdNode.Start.Line - 1;
                    if (!string.IsNullOrEmpty(realNewClassModel.Guid))
                    {
                        // Replace the Guid
                        linesToChange[line] = linesToChange[line].ReplaceFirst(oldGuid, realNewClassModel.Guid);
                    }
                    else
                    {
                        Debug.Log("Found empty guid in a scene! Will not replace");
                        continue;
                    }

                    if (!String.IsNullOrEmpty(oldFileId))
                    {
                        linesToChange[line] = linesToChange[line].ReplaceFirst(oldFileId, realNewClassModel.FileID);
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError("Could not migrate guid and fileID in file: " + fileToChange + "\r\n node: " +
                                   document + "\r\nException" + e);
                }
            }

            return(linesToChange);
        }
Exemplo n.º 28
0
        public object NodeToType(Type type, YamlNode node)
        {
            var underlyingType = Nullable.GetUnderlyingType(type) ?? type;

            // special snowflake string
            if (type == typeof(String))
            {
                return(node.ToString());
            }

            // val primitives
            if (underlyingType.IsPrimitive || underlyingType == typeof(decimal))
            {
                return(StringToType(type, node.ToString()));
            }

            // array
            if (type.IsArray)
            {
                var listNode = (YamlSequenceNode)node;
                var newArray = (Array)Activator.CreateInstance(type, listNode.Children.Count) !;

                var idx = 0;
                foreach (var entryNode in listNode)
                {
                    var value = NodeToType(type.GetElementType() !, entryNode);
                    newArray.SetValue(value, idx++);
                }

                return(newArray);
            }

            // val enum
            if (type.IsEnum)
            {
                return(Enum.Parse(type, node.ToString()));
            }

            // IReadOnlyList<T>/IReadOnlyCollection<T>
            if (TryGenericReadOnlyCollectionType(type, out var collectionType))
            {
                var listNode = (YamlSequenceNode)node;
                var elems    = listNode.Children;
                // Deserialize to an array because that is much more efficient, and allowed.
                var newList = (IList)Array.CreateInstance(collectionType, elems.Count);

                for (var i = 0; i < elems.Count; i++)
                {
                    newList[i] = NodeToType(collectionType, elems[i]);
                }

                return(newList);
            }

            // List<T>
            if (TryGenericListType(type, out var listType))
            {
                var listNode = (YamlSequenceNode)node;
                var newList  = (IList)Activator.CreateInstance(type, listNode.Children.Count) !;

                foreach (var entryNode in listNode)
                {
                    var value = NodeToType(listType, entryNode);
                    newList.Add(value);
                }

                return(newList);
            }

            // Dictionary<K,V>/IReadOnlyDictionary<K,V>
            if (TryGenericReadDictType(type, out var keyType, out var valType, out var dictType))
            {
                var dictNode = (YamlMappingNode)node;
                var newDict  = (IDictionary)Activator.CreateInstance(dictType, dictNode.Children.Count) !;

                foreach (var kvEntry in dictNode.Children)
                {
                    var keyValue = NodeToType(keyType, kvEntry.Key);
                    var valValue = NodeToType(valType, kvEntry.Value);

                    newDict.Add(keyValue, valValue);
                }

                return(newDict);
            }

            // HashSet<T>
            if (TryGenericHashSetType(type, out var setType))
            {
                var nodes       = ((YamlSequenceNode)node).Children;
                var valuesArray = Array.CreateInstance(setType, new[] { nodes.Count }) !;

                for (var i = 0; i < nodes.Count; i++)
                {
                    var value = NodeToType(setType, nodes[i]);
                    valuesArray.SetValue(value, i);
                }

                var newSet = Activator.CreateInstance(type, valuesArray) !;

                return(newSet);
            }

            // Hand it to the context.
            if (_context != null && _context.TryNodeToType(node, type, out var contextObj))
            {
                return(contextObj);
            }

            // custom TypeSerializer
            if (_typeSerializers.TryGetValue(type, out var serializer))
            {
                return(serializer.NodeToType(type, node, this));
            }

            // IExposeData.
            if (typeof(IExposeData).IsAssignableFrom(type))
            {
                if (!(node is YamlMappingNode mapNode))
                {
                    throw new InvalidOperationException($"Cannot read from IExposeData on non-mapping node. Type: '{type}'");
                }

                var concreteType = type;
                if (type.IsAbstract || type.IsInterface)
                {
                    var tag = node.Tag;
                    if (string.IsNullOrWhiteSpace(tag))
                    {
                        throw new YamlException($"Type '{type}' is abstract, but there is no yaml tag for the concrete type.");
                    }

                    if (tag.StartsWith("!type:"))
                    {
                        concreteType = ResolveConcreteType(type, tag["!type:".Length..]);
Exemplo n.º 29
0
            public override object NodeToType(Type type, YamlNode node, YamlObjectSerializer serializer)
            {
                var val = int.Parse(node.ToString(), CultureInfo.InvariantCulture);

                return(new MapId(val));
            }
Exemplo n.º 30
0
        public Config(byte[] rom)
        {
            const string configFile = "MP2K.yaml";

            using (StreamReader fileStream = File.OpenText(Util.Utils.CombineWithBaseDirectory(configFile)))
            {
                string gcv = string.Empty;
                try
                {
                    ROM      = rom;
                    Reader   = new EndianBinaryReader(new MemoryStream(rom));
                    GameCode = Reader.ReadString(4, 0xAC);
                    Version  = Reader.ReadByte(0xBC);
                    gcv      = $"{GameCode}_{Version:X2}";
                    var yaml = new YamlStream();
                    yaml.Load(fileStream);

                    var             mapping = (YamlMappingNode)yaml.Documents[0].RootNode;
                    YamlMappingNode game;
                    try
                    {
                        game = (YamlMappingNode)mapping.Children.GetValue(gcv);
                    }
                    catch (BetterKeyNotFoundException)
                    {
                        throw new Exception(string.Format(Strings.ErrorParseConfig, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KMissingGameCode, gcv)));
                    }

                    YamlNode nameNode               = null,
                             songTableOffsetsNode   = null,
                             songTableSizesNode     = null,
                             sampleRateNode         = null,
                             reverbTypeNode         = null,
                             reverbNode             = null,
                             volumeNode             = null,
                             hasGoldenSunSynthsNode = null,
                             hasPokemonCompression  = null;
                    void Load(YamlMappingNode gameToLoad)
                    {
                        if (gameToLoad.Children.TryGetValue("Copy", out YamlNode node))
                        {
                            YamlMappingNode copyGame;
                            try
                            {
                                copyGame = (YamlMappingNode)mapping.Children.GetValue(node);
                            }
                            catch (BetterKeyNotFoundException ex)
                            {
                                throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KCopyInvalidGameCode, ex.Key)));
                            }
                            Load(copyGame);
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Name), out node))
                        {
                            nameNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(SongTableOffsets), out node))
                        {
                            songTableOffsetsNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(SongTableSizes), out node))
                        {
                            songTableSizesNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(SampleRate), out node))
                        {
                            sampleRateNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(ReverbType), out node))
                        {
                            reverbTypeNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Reverb), out node))
                        {
                            reverbNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Volume), out node))
                        {
                            volumeNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(HasGoldenSunSynths), out node))
                        {
                            hasGoldenSunSynthsNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(HasPokemonCompression), out node))
                        {
                            hasPokemonCompression = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Playlists), out node))
                        {
                            var playlists = (YamlMappingNode)node;
                            foreach (KeyValuePair <YamlNode, YamlNode> kvp in playlists)
                            {
                                string name  = kvp.Key.ToString();
                                var    songs = new List <Song>();
                                foreach (KeyValuePair <YamlNode, YamlNode> song in (YamlMappingNode)kvp.Value)
                                {
                                    long songIndex = Util.Utils.ParseValue(string.Format(Strings.ConfigKeySubkey, nameof(Playlists)), song.Key.ToString(), 0, long.MaxValue);
                                    if (songs.Any(s => s.Index == songIndex))
                                    {
                                        throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KSongRepeated, name, songIndex)));
                                    }
                                    songs.Add(new Song(songIndex, song.Value.ToString()));
                                }
                                Playlists.Add(new Playlist(name, songs));
                            }
                        }
                    }

                    Load(game);

                    if (nameNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(Name), null);
                    }
                    Name = nameNode.ToString();
                    if (songTableOffsetsNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(SongTableOffsets), null);
                    }
                    string[] songTables    = songTableOffsetsNode.ToString().SplitSpace(StringSplitOptions.RemoveEmptyEntries);
                    int      numSongTables = songTables.Length;
                    if (numSongTables == 0)
                    {
                        throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyNoEntries, nameof(SongTableOffsets))));
                    }
                    if (songTableSizesNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(SongTableSizes), null);
                    }
                    string[] sizes = songTableSizesNode.ToString().SplitSpace(StringSplitOptions.RemoveEmptyEntries);
                    if (sizes.Length != numSongTables)
                    {
                        throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KSongTableCounts, nameof(SongTableSizes), nameof(SongTableOffsets))));
                    }
                    SongTableOffsets = new int[numSongTables];
                    SongTableSizes   = new long[numSongTables];
                    int maxOffset = rom.Length - 1;
                    for (int i = 0; i < numSongTables; i++)
                    {
                        SongTableSizes[i]   = Util.Utils.ParseValue(nameof(SongTableSizes), sizes[i], 1, maxOffset);
                        SongTableOffsets[i] = (int)Util.Utils.ParseValue(nameof(SongTableOffsets), songTables[i], 0, maxOffset);
                    }
                    if (sampleRateNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(SampleRate), null);
                    }
                    SampleRate = (int)Util.Utils.ParseValue(nameof(SampleRate), sampleRateNode.ToString(), 0, Utils.FrequencyTable.Length - 1);
                    if (reverbTypeNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(ReverbType), null);
                    }
                    ReverbType = Util.Utils.ParseEnum <ReverbType>(nameof(ReverbType), reverbTypeNode.ToString());
                    if (reverbNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(Reverb), null);
                    }
                    Reverb = (byte)Util.Utils.ParseValue(nameof(Reverb), reverbNode.ToString(), byte.MinValue, byte.MaxValue);
                    if (volumeNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(Volume), null);
                    }
                    Volume = (byte)Util.Utils.ParseValue(nameof(Volume), volumeNode.ToString(), 0, 15);
                    if (hasGoldenSunSynthsNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(HasGoldenSunSynths), null);
                    }
                    HasGoldenSunSynths = Util.Utils.ParseBoolean(nameof(HasGoldenSunSynths), hasGoldenSunSynthsNode.ToString());
                    if (hasPokemonCompression == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(HasPokemonCompression), null);
                    }
                    HasPokemonCompression = Util.Utils.ParseBoolean(nameof(HasPokemonCompression), hasPokemonCompression.ToString());

                    // The complete playlist
                    if (!Playlists.Any(p => p.Name == "Music"))
                    {
                        Playlists.Insert(0, new Playlist(Strings.PlaylistMusic, Playlists.SelectMany(p => p.Songs).Distinct().OrderBy(s => s.Index)));
                    }
                }
                catch (BetterKeyNotFoundException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyMissing, ex.Key)));
                }
                catch (InvalidValueException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + ex.Message));
                }
                catch (YamlDotNet.Core.YamlException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorParseConfig, configFile, Environment.NewLine + ex.Message));
                }
            }
        }