Exemplo n.º 1
0
        /// <summary>
        /// Loads ParserTargets from other assemblies in GameData/
        /// </summary>
        public static void LoadExternalParserTargets(ConfigNode node, String modName = "Default", Boolean getChilds = true)
        {
            // Look for types in other assemblies with the ExternalParserTarget attribute and the parentNodeName equal to this node's name
            try
            {
                foreach (Type type in ModTypes)
                {
                    try
                    {
                        ParserTargetExternal[] attributes = (ParserTargetExternal[])type.GetCustomAttributes(typeof(ParserTargetExternal), false);
                        if (attributes.Length == 0)
                        {
                            continue;
                        }
                        ParserTargetExternal external = attributes[0];
                        if (node.name != external.parentNodeName)
                        {
                            continue;
                        }
                        String nodeName = external.configNodeName ?? type.Name;

                        // Get settings data
                        ParserOptions.Data data = ParserOptions.options[modName];

                        if (!node.HasNode(nodeName))
                        {
                            continue;
                        }
                        try
                        {
                            data.logCallback("Parsing ParserTarget " + nodeName + " in node " + external.parentNodeName + " from Assembly " + type.Assembly.FullName);
                            ConfigNode nodeToLoad = node.GetNode(nodeName);
                            Object     obj        = CreateObjectFromConfigNode(type, nodeToLoad, modName, getChilds);
                        }
                        catch (MissingMethodException missingMethod)
                        {
                            data.logCallback("Failed to load ParserTargetExternal " + nodeName + " because it does not have a parameterless constructor");
                            data.errorCallback(missingMethod);
                        }
                        catch (Exception exception)
                        {
                            data.logCallback("Failed to load ParserTargetExternal " + nodeName + " from node " + external.parentNodeName);
                            data.errorCallback(exception);
                        }
                    }
                    catch (TypeLoadException)
                    {
                        // ignored
                    }
                }
            }
            catch (ReflectionTypeLoadException)
            {
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Load data for ParserTarget field or property from a configuration node
        /// </summary>
        /// <param name="member">Member to load data for</param>
        /// <param name="o">Instance of the object which owns member</param>
        /// <param name="node">Configuration node from which to load data</param>        /// <param name="modName">The name of the mod that corresponds to the entry in ParserOptions</param>
        /// <param name="getChilds">Whether getters on the object should get called</param>
        public static void LoadObjectMemberFromConfigurationNode(MemberInfo member, object o, ConfigNode node, String modName = "Default", Boolean getChilds = true)
        {
            // Get the parser target, only one is allowed so it will be first
            ParserTarget target = ((ParserTarget[])member.GetCustomAttributes(typeof(ParserTarget), true))[0];

            // Figure out if this field exists and if we care
            Boolean isNode  = node.HasNode(target.fieldName);
            Boolean isValue = node.HasValue(target.fieldName);

            // Obtain the type the member is (can only be field or property)
            Type   targetType;
            Object targetValue = null;

            if (member.MemberType == MemberTypes.Field)
            {
                targetType  = ((FieldInfo)member).FieldType;
                targetValue = getChilds ? ((FieldInfo)member).GetValue(o) : null;
            }
            else
            {
                targetType = ((PropertyInfo)member).PropertyType;
                try
                {
                    if (((PropertyInfo)member).CanRead && getChilds)
                    {
                        targetValue = ((PropertyInfo)member).GetValue(o, null);
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            }

            // Get settings data
            ParserOptions.Data data = ParserOptions.options[modName];

            // Log
            data.logCallback("Parsing Target " + target.fieldName + " in (" + o.GetType() + ") as (" + targetType + ")");

            // If there was no data found for this node
            if (!isNode && !isValue)
            {
                if (!target.optional && !(target.allowMerge && targetValue != null))
                {
                    // Error - non optional field is missing
                    throw new ParserTargetMissingException("Missing non-optional field: " + o.GetType() + "." + target.fieldName);
                }

                // Nothing to do, so DONT return!
                return;
            }

            // Does this node have a required config source type (and if so, check if valid)
            RequireConfigType[] attributes = (RequireConfigType[])member.GetCustomAttributes(typeof(RequireConfigType), true);
            if (attributes.Length > 0)
            {
                if ((attributes[0].type == ConfigType.Node && !isNode) || (attributes[0].type == ConfigType.Value && !isValue))
                {
                    throw new ParserTargetTypeMismatchException(target.fieldName + " requires config value of " + attributes[0].type);
                }
            }

            // If this object is a value (attempt no merge here)
            if (isValue)
            {
                // The node value
                String nodeValue = node.GetValue(target.fieldName);

                // Merge all values of the node
                if (target.getAll != null)
                {
                    nodeValue = String.Join(target.getAll, node.GetValues(target.fieldName));
                }

                // If the target is a string, it works natively
                if (targetType == typeof(String))
                {
                    targetValue = nodeValue;
                }

                // Figure out if this object is a parsable type
                else if (typeof(IParsable).IsAssignableFrom(targetType))
                {
                    // Create a new object
                    IParsable targetParsable = (IParsable)Activator.CreateInstance(targetType);
                    targetParsable.SetFromString(nodeValue);
                    targetValue = targetParsable;
                }

                // Throw exception or print error
                else
                {
                    data.logCallback("[Kopernicus]: Configuration.Parser: ParserTarget \"" + target.fieldName + "\" is a non parsable type: " + targetType);
                    return;
                }
            }

            // If this object is a node (potentially merge)
            else
            {
                // If the target type is a ConfigNode, this works natively
                if (targetType == typeof(ConfigNode))
                {
                    targetValue = node.GetNode(target.fieldName);
                }

                // We need to get an instance of the object we are trying to populate
                // If we are not allowed to merge, or the object does not exist, make a new instance
                else if (targetValue == null || !target.allowMerge)
                {
                    targetValue = CreateObjectFromConfigNode(targetType, node.GetNode(target.fieldName), modName, target.getChild);
                }

                // Otherwise we can merge this value
                else
                {
                    LoadObjectFromConfigurationNode(targetValue, node.GetNode(target.fieldName), modName, target.getChild);
                }
            }

            // If the member type is a field, set the value
            if (member.MemberType == MemberTypes.Field)
            {
                ((FieldInfo)member).SetValue(o, targetValue);
            }

            // If the member wasn't a field, it must be a property.  If the property is writable, set it.
            else if (((PropertyInfo)member).CanWrite)
            {
                ((PropertyInfo)member).SetValue(o, targetValue, null);
            }
        }